diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | gtk/window-decorator/gtk-window-decorator.c | 2629 | ||||
-rw-r--r-- | plugins/imgpng/src/imgpng.cpp | 4 | ||||
-rw-r--r-- | plugins/place/src/place.cpp | 10 | ||||
-rw-r--r-- | src/window.cpp | 15 |
5 files changed, 1896 insertions, 764 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b760c6c..4848e66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,8 @@ set (GETTEXT_PACKAGE compiz) find_package (Boost 1.34.0 REQUIRED) set (COMPIZ_REQUIRES + x11 + xext xdamage xcomposite x11-xcb diff --git a/gtk/window-decorator/gtk-window-decorator.c b/gtk/window-decorator/gtk-window-decorator.c index 213ab49..aa17348 100644 --- a/gtk/window-decorator/gtk-window-decorator.c +++ b/gtk/window-decorator/gtk-window-decorator.c @@ -242,9 +242,9 @@ static double decoration_alpha = 0.5; #define SWITCHER_SPACE 40 static decor_extents_t _shadow_extents = { 0, 0, 0, 0 }; -static decor_extents_t _win_extents = { 6, 6, 4, 6 }; +static decor_extents_t _win_extents = { 6, 6, 6, 6 }; static decor_extents_t _max_win_extents = { 6, 6, 4, 6 }; -static decor_extents_t _default_win_extents = { 6, 6, 4, 6 }; +static decor_extents_t _default_win_extents = { 6, 6, 6, 6 }; static decor_extents_t _switcher_extents = { 6, 6, 6, 6 + SWITCHER_SPACE }; static int titlebar_height = 17; @@ -304,7 +304,8 @@ static decor_shadow_t *switcher_shadow = NULL; static GdkPixmap *decor_normal_pixmap = NULL; static GdkPixmap *decor_active_pixmap = NULL; -static Atom frame_window_atom; +static Atom frame_input_window_atom; +static Atom frame_output_window_atom; static Atom win_decor_atom; static Atom win_blur_decor_atom; static Atom wm_move_resize_atom; @@ -314,8 +315,6 @@ static Atom mwm_hints_atom; static Atom switcher_fg_atom; static Atom toolkit_action_atom; -static Atom toolkit_action_main_menu_atom; -static Atom toolkit_action_run_dialog_atom; static Atom toolkit_action_window_menu_atom; static Atom toolkit_action_force_quit_dialog_atom; @@ -374,15 +373,24 @@ typedef struct _decor_color { double b; } decor_color_t; + #define IN_EVENT_WINDOW (1 << 0) #define PRESSED_EVENT_WINDOW (1 << 1) typedef struct _decor { + WnckWindow *win; Window event_windows[3][3]; Window button_windows[BUTTON_NUM]; + Box event_window_pos[3][3]; + Box button_window_pos[BUTTON_NUM]; + Box *last_pos_entered; guint button_states[BUTTON_NUM]; GdkPixmap *pixmap; GdkPixmap *buffer_pixmap; + GdkWindow *frame_window; + GtkWidget *decor_window; + GtkWidget *decor_event_box; + GtkWidget *decor_image; GdkGC *gc; decor_layout_t border_layout; decor_context_t *context; @@ -404,9 +412,28 @@ typedef struct _decor { WnckWindowActions actions; XID prop_xid; GtkWidget *force_quit_dialog; + Bool created; void (*draw) (struct _decor *d); } decor_t; +typedef struct _decor_event { + guint time; + guint window; + guint x; + guint y; + guint x_root; + guint y_root; + guint button; +} decor_event; + +typedef enum _decor_event_type { + GButtonPress = 1, + GButtonRelease, + GEnterNotify, + GLeaveNotify, + GMotionNotify +} decor_event_type; + void (*theme_draw_window_decoration) (decor_t *d); gboolean (*theme_calc_decoration_size) (decor_t *d, int client_width, @@ -433,11 +460,12 @@ gboolean (*theme_get_button_position) (decor_t *d, gint *w, gint *h); -typedef void (*event_callback) (WnckWindow *win, XEvent *event); +typedef void (*event_callback) (WnckWindow *win, decor_event *gtkwd_event, decor_event_type gtkwd_type); static char *program_name; -static GtkWidget *style_window; +static GtkWidget *sytle_window_rgba; +static GtkWidget *sytle_window_rgb; static GtkWidget *switcher_label; static GHashTable *frame_table; @@ -471,7 +499,8 @@ static gint switcher_width; static gint switcher_height; static Window switcher_selected_window = None; -static XRenderPictFormat *xformat; +static XRenderPictFormat *xformat32; +static XRenderPictFormat *xformat24; static void decor_update_blur_property (decor_t *d, @@ -569,11 +598,18 @@ decor_update_window_property (decor_t *d) extents.top += titlebar_height; - decor_quads_to_property (data, GDK_PIXMAP_XID (d->pixmap), + if (d->frame_window) + { + decor_gen_window_property (data, &extents, &extents, 20, 20); + } + else + { + decor_quads_to_property (data, GDK_PIXMAP_XID (d->pixmap), &extents, &extents, ICON_SPACE + d->button_width, 0, quads, nQuad); + } gdk_error_trap_push (); XChangeProperty (xdisplay, d->prop_xid, @@ -636,14 +672,26 @@ gdk_cairo_set_source_color_alpha (cairo_t *cr, alpha); } +static inline GdkWindow * +create_gdk_window (Window xframe) +{ + GdkWindow *window = gdk_window_foreign_new (xframe); + GdkScreen *screen = gdk_display_get_default_screen (gdk_display_get_default ()); + GdkColormap *cmap = gdk_screen_get_rgb_colormap (screen); + + gdk_drawable_set_colormap (GDK_DRAWABLE (window), cmap); + return window; +} + static GdkPixmap * create_pixmap (int w, - int h) + int h, + int depth) { if (w == 0 || h ==0) abort (); - return gdk_pixmap_new (GDK_DRAWABLE (style_window->window), w, h, 32); + return gdk_pixmap_new (GDK_DRAWABLE (sytle_window_rgba->window), w, h, depth); } #define CORNER_TOPLEFT (1 << 0) @@ -925,6 +973,7 @@ draw_window_decoration (decor_t *d) { cairo_t *cr; GtkStyle *style; + GdkDrawable *drawable; decor_color_t color; double alpha; double x1, y1, x2, y2, x, y, h; @@ -935,7 +984,8 @@ draw_window_decoration (decor_t *d) if (!d->pixmap) return; - style = gtk_widget_get_style (style_window); + style = gtk_widget_get_style (sytle_window_rgba); + if (d->state & (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY | WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY)) @@ -945,10 +995,30 @@ draw_window_decoration (decor_t *d) color.g = style->bg[GTK_STATE_NORMAL].green / 65535.0; color.b = style->bg[GTK_STATE_NORMAL].blue / 65535.0; - if (d->buffer_pixmap) - cr = gdk_cairo_create (GDK_DRAWABLE (d->buffer_pixmap)); + if (d->frame_window) + { + GdkScreen *screen = gdk_display_get_default_screen (gdk_display_get_default ()); + GdkColormap *cmap; + + if (gdk_drawable_get_depth (GDK_DRAWABLE (d->pixmap)) == 32) + cmap = gdk_screen_get_rgba_colormap (screen); + else + cmap = gdk_screen_get_rgb_colormap (screen); + + gdk_drawable_set_colormap (GDK_DRAWABLE (d->pixmap), cmap); + gdk_drawable_set_colormap (GDK_DRAWABLE (d->buffer_pixmap), cmap); + + drawable = GDK_DRAWABLE (d->buffer_pixmap); + } + else if (d->buffer_pixmap) + drawable = GDK_DRAWABLE (d->buffer_pixmap); else - cr = gdk_cairo_create (GDK_DRAWABLE (d->pixmap)); + drawable = GDK_DRAWABLE (d->pixmap); + + cr = gdk_cairo_create (GDK_DRAWABLE (drawable)); + + if (!cr) + return; cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); @@ -963,7 +1033,8 @@ draw_window_decoration (decor_t *d) cairo_set_line_width (cr, 1.0); - draw_shadow_background (d, cr, d->shadow, d->context); + if (!d->frame_window) + draw_shadow_background (d, cr, d->shadow, d->context); if (d->active) { @@ -1121,6 +1192,7 @@ draw_window_decoration (decor_t *d) CORNER_BOTTOMRIGHT) & corners); cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.4); + cairo_stroke (cr); cairo_translate (cr, -2.0, -2.0); @@ -1133,6 +1205,7 @@ draw_window_decoration (decor_t *d) CORNER_BOTTOMRIGHT) & corners); cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.1); + cairo_stroke (cr); cairo_translate (cr, 1.0, 1.0); @@ -1176,6 +1249,7 @@ draw_window_decoration (decor_t *d) gdk_cairo_set_source_color_alpha (cr, &style->fg[GTK_STATE_NORMAL], alpha * 0.75); + cairo_move_to (cr, x, y); draw_close_button (d, cr, 3.0); cairo_fill (cr); @@ -1197,6 +1271,7 @@ draw_window_decoration (decor_t *d) gdk_cairo_set_source_color_alpha (cr, &style->fg[GTK_STATE_NORMAL], STROKE_ALPHA); + cairo_move_to (cr, x, y); if (d->state & (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY | @@ -1213,6 +1288,7 @@ draw_window_decoration (decor_t *d) gdk_cairo_set_source_color_alpha (cr, &style->fg[GTK_STATE_NORMAL], alpha * 0.75); + cairo_move_to (cr, x, y); if (d->state & (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY | @@ -1238,6 +1314,8 @@ draw_window_decoration (decor_t *d) gdk_cairo_set_source_color_alpha (cr, &style->fg[GTK_STATE_NORMAL], STROKE_ALPHA); + + cairo_move_to (cr, x, y); draw_min_button (d, cr, 4.0); button_state_paint (cr, style, &color, @@ -1248,6 +1326,7 @@ draw_window_decoration (decor_t *d) gdk_cairo_set_source_color_alpha (cr, &style->fg[GTK_STATE_NORMAL], alpha * 0.75); + cairo_move_to (cr, x, y); draw_min_button (d, cr, 4.0); cairo_fill (cr); @@ -1312,6 +1391,12 @@ draw_window_decoration (decor_t *d) d->width, d->height); + if (d->frame_window) + { + gtk_image_set_from_pixmap (GTK_IMAGE (d->decor_image), d->pixmap, NULL); + gtk_window_resize (GTK_WINDOW (d->decor_window), d->width, d->height); + } + if (d->prop_xid) { decor_update_window_property (d); @@ -1374,12 +1459,19 @@ decor_update_meta_window_property (decor_t *d, extents.top += titlebar_height; max_extents.top += max_titlebar_height; - - decor_quads_to_property (data, GDK_PIXMAP_XID (d->pixmap), - &extents, &max_extents, - ICON_SPACE + d->button_width, - 0, - quads, nQuad); + + if (d->frame_window) + { + decor_gen_window_property (data, &extents, &max_extents, 20, 20); + } + else + { + decor_quads_to_property (data, GDK_PIXMAP_XID (d->pixmap), + &extents, &max_extents, + ICON_SPACE + d->button_width, + 0, + quads, nQuad); + } gdk_error_trap_push (); XChangeProperty (xdisplay, d->prop_xid, @@ -1849,16 +1941,40 @@ meta_draw_window_decoration (decor_t *d) gboolean shade_alpha = (d->active) ? meta_active_shade_opacity : meta_shade_opacity; MetaFrameStyle *frame_style; + GtkWidget *style_window; GdkColor bg_color; double bg_alpha; if (!d->pixmap || !d->picture) return; + if (d->frame_window) + { + GdkScreen *screen = gdk_display_get_default_screen (gdk_display_get_default ()); + GdkColormap *cmap; + + if (gdk_drawable_get_depth (GDK_DRAWABLE (d->pixmap)) == 32) + cmap = gdk_screen_get_rgba_colormap (screen); + else + cmap = gdk_screen_get_rgb_colormap (screen); + + gdk_drawable_set_colormap (GDK_DRAWABLE (d->pixmap), cmap); + gdk_drawable_set_colormap (GDK_DRAWABLE (d->buffer_pixmap), cmap); + } + if (decoration_alpha == 1.0) alpha = 1.0; - style = gtk_widget_get_style (style_window); + if (gdk_drawable_get_depth (GDK_DRAWABLE (d->pixmap)) == 32) + { + style = gtk_widget_get_style (sytle_window_rgba); + style_window = sytle_window_rgba; + } + else + { + style = gtk_widget_get_style (sytle_window_rgb); + style_window = sytle_window_rgb; + } drawable = d->buffer_pixmap ? d->buffer_pixmap : d->pixmap; @@ -1873,7 +1989,7 @@ meta_draw_window_decoration (decor_t *d) /* we only have to redraw the shadow background when decoration changed size */ - if (d->prop_xid || !d->buffer_pixmap) + if ((d->prop_xid || !d->buffer_pixmap) && !d->frame_window) draw_shadow_background (d, cr, d->shadow, d->context); for (i = 0; i < META_BUTTON_TYPE_LAST; i++) @@ -1907,15 +2023,36 @@ meta_draw_window_decoration (decor_t *d) if (rect.width && size) { - pixmap = create_pixmap (rect.width, size); + if (d->frame_window) + { + pixmap = create_pixmap (rect.width, size, gdk_drawable_get_depth (GDK_DRAWABLE (d->frame_window))); + + GdkScreen *screen = gdk_display_get_default_screen (gdk_display_get_default ()); + GdkColormap *cmap; + + if (gdk_drawable_get_depth (GDK_DRAWABLE (d->pixmap)) == 32) + cmap = gdk_screen_get_rgba_colormap (screen); + else + cmap = gdk_screen_get_rgb_colormap (screen); + + gdk_drawable_set_colormap (GDK_DRAWABLE (pixmap), cmap); + } + else + pixmap = create_pixmap (rect.width, size, 32); cr = gdk_cairo_create (GDK_DRAWABLE (pixmap)); gdk_cairo_set_source_color_alpha (cr, &bg_color, bg_alpha); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - src = XRenderCreatePicture (xdisplay, - GDK_PIXMAP_XID (pixmap), - xformat, 0, NULL); + if (gdk_drawable_get_depth (GDK_DRAWABLE (pixmap)) == 32 || + !d->frame_window) + src = XRenderCreatePicture (xdisplay, + GDK_PIXMAP_XID (pixmap), + xformat32, 0, NULL); + else + src = XRenderCreatePicture (xdisplay, + GDK_PIXMAP_XID (pixmap), + xformat24, 0, NULL); if (fgeom.top_height) { @@ -2009,15 +2146,36 @@ meta_draw_window_decoration (decor_t *d) if (size && rect.height) { - pixmap = create_pixmap (size, rect.height); + if (d->frame_window) + { + pixmap = create_pixmap (rect.width, size, gdk_drawable_get_depth (GDK_DRAWABLE (d->frame_window))); + + GdkScreen *screen = gdk_display_get_default_screen (gdk_display_get_default ()); + GdkColormap *cmap; + + if (gdk_drawable_get_depth (GDK_DRAWABLE (d->pixmap)) == 32) + cmap = gdk_screen_get_rgba_colormap (screen); + else + cmap = gdk_screen_get_rgb_colormap (screen); + + gdk_drawable_set_colormap (GDK_DRAWABLE (pixmap), cmap); + } + else + pixmap = create_pixmap (rect.width, size, 32); cr = gdk_cairo_create (GDK_DRAWABLE (pixmap)); gdk_cairo_set_source_color_alpha (cr, &bg_color, bg_alpha); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - src = XRenderCreatePicture (xdisplay, - GDK_PIXMAP_XID (pixmap), - xformat, 0, NULL); + if (gdk_drawable_get_depth (GDK_DRAWABLE (pixmap)) == 32 || + !d->frame_window) + src = XRenderCreatePicture (xdisplay, + GDK_PIXMAP_XID (pixmap), + xformat32, 0, NULL); + else + src = XRenderCreatePicture (xdisplay, + GDK_PIXMAP_XID (pixmap), + xformat24, 0, NULL); if (fgeom.left_width) { @@ -2117,6 +2275,12 @@ meta_draw_window_decoration (decor_t *d) d->width, d->height); + if (d->frame_window) + { + gtk_image_set_from_pixmap (GTK_IMAGE (d->decor_image), d->pixmap, NULL); + gtk_window_resize (GTK_WINDOW (d->decor_window), d->width, d->height); + } + if (d->prop_xid) { /* translate from frame to client window space */ @@ -2170,7 +2334,7 @@ decor_update_switcher_property (decor_t *d) &_switcher_extents, &_switcher_extents, 0, 0, quads, nQuad); - style = gtk_widget_get_style (style_window); + style = gtk_widget_get_style (sytle_window_rgba); fgColor[0] = style->fg[GTK_STATE_NORMAL].red; fgColor[1] = style->fg[GTK_STATE_NORMAL].green; @@ -2205,7 +2369,7 @@ draw_switcher_background (decor_t *d) if (!d->buffer_pixmap) return; - style = gtk_widget_get_style (style_window); + style = gtk_widget_get_style (sytle_window_rgba); color.r = style->bg[GTK_STATE_NORMAL].red / 65535.0; color.g = style->bg[GTK_STATE_NORMAL].green / 65535.0; @@ -2404,7 +2568,7 @@ draw_switcher_foreground (decor_t *d) if (!d->pixmap || !d->buffer_pixmap) return; - style = gtk_widget_get_style (style_window); + style = gtk_widget_get_style (sytle_window_rgba); cr = gdk_cairo_create (GDK_DRAWABLE (d->buffer_pixmap)); @@ -2495,7 +2659,7 @@ queue_decor_draw (decor_t *d) } static GdkPixmap * -pixmap_new_from_pixbuf (GdkPixbuf *pixbuf) +pixmap_new_from_pixbuf (GdkPixbuf *pixbuf, int depth) { GdkPixmap *pixmap; guint width, height; @@ -2504,7 +2668,7 @@ pixmap_new_from_pixbuf (GdkPixbuf *pixbuf) width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); - pixmap = create_pixmap (width, height); + pixmap = create_pixmap (width, height, depth); if (!pixmap) return NULL; @@ -2604,14 +2768,15 @@ update_default_decorations (GdkScreen *screen) nQuad = decor_set_lSrStSbS_window_quads (quads, d.context, &d.border_layout); - decor_normal_pixmap = create_pixmap (d.width, d.height); + decor_normal_pixmap = create_pixmap (d.width, d.height, 32); + if (decor_normal_pixmap) { d.pixmap = decor_normal_pixmap; d.active = FALSE; d.picture = XRenderCreatePicture (xdisplay, GDK_PIXMAP_XID (d.pixmap), - xformat, 0, NULL); + xformat32, 0, NULL); (*d.draw) (&d); @@ -2630,14 +2795,15 @@ update_default_decorations (GdkScreen *screen) if (decor_active_pixmap) g_object_unref (G_OBJECT (decor_active_pixmap)); - decor_active_pixmap = create_pixmap (d.width, d.height); + decor_active_pixmap = create_pixmap (d.width, d.height, 32); + if (decor_active_pixmap) { d.pixmap = decor_active_pixmap; d.active = TRUE; d.picture = XRenderCreatePicture (xdisplay, GDK_PIXMAP_XID (d.pixmap), - xformat, 0, NULL); + xformat32, 0, NULL); (*d.draw) (&d); @@ -3116,13 +3282,20 @@ update_event_windows (WnckWindow *win) (*theme_get_event_window_position) (d, i, j, width, height, &x, &y, &w, &h); - if (w != 0 && h != 0) + if (d->frame_window) + { + d->event_window_pos[i][j].x1 = x; + d->event_window_pos[i][j].x2 = x + w; + d->event_window_pos[i][j].y1 = y; + d->event_window_pos[i][j].y2 = y + h; + } + else if (!d->frame_window && w != 0 && h != 0) { XMapWindow (xdisplay, d->event_windows[i][j]); XMoveResizeWindow (xdisplay, d->event_windows[i][j], x, y, w, h); } - else + else if (!d->frame_window) { XUnmapWindow (xdisplay, d->event_windows[i][j]); } @@ -3158,18 +3331,36 @@ update_event_windows (WnckWindow *win) }; - if (button_actions[i] && !(actions & button_actions[i])) + if (d->frame_window && + button_actions[i] && !(actions & button_actions[i])) + { + d->button_window_pos[i].x1 = 0; + d->button_window_pos[i].y1 = 0; + d->button_window_pos[i].x2 = 0; + d->button_window_pos[i].y2 = 0; + } + else if (!d->frame_window && + button_actions[i] && !(actions & button_actions[i])) { XUnmapWindow (xdisplay, d->button_windows[i]); continue; } - if ((*theme_get_button_position) (d, i, width, height, &x, &y, &w, &h)) + if (d->frame_window && + (*theme_get_button_position) (d, i, width, height, &x, &y, &w, &h)) + { + d->button_window_pos[i].x1 = x; + d->button_window_pos[i].y1 = y; + d->button_window_pos[i].x2 = x + w; + d->button_window_pos[i].y2 = y + h; + } + else if (!d->frame_window && + (*theme_get_button_position) (d, i, width, height, &x, &y, &w, &h)) { XMapWindow (xdisplay, d->button_windows[i]); XMoveResizeWindow (xdisplay, d->button_windows[i], x, y, w, h); } - else + else if (!d->frame_window) { XUnmapWindow (xdisplay, d->button_windows[i]); } @@ -3306,7 +3497,8 @@ update_window_decoration_icon (WnckWindow *win) g_object_ref (G_OBJECT (d->icon_pixbuf)); - d->icon_pixmap = pixmap_new_from_pixbuf (d->icon_pixbuf); + d->icon_pixmap = pixmap_new_from_pixbuf (d->icon_pixbuf, + 24); cr = gdk_cairo_create (GDK_DRAWABLE (d->icon_pixmap)); d->icon = cairo_pattern_create_for_surface (cairo_get_target (cr)); cairo_destroy (cr); @@ -3366,25 +3558,54 @@ calc_decoration_size (decor_t *d, decor_layout_t layout; int top_width; - calc_button_size (d); + /* To avoid wasting texture memory, we only calculate the minimal + * required decoration size then clip and stretch the texture where + * appropriate + */ + + if (!d->frame_window) + { + calc_button_size (d); - if (w < ICON_SPACE + d->button_width) - return FALSE; + if (w < ICON_SPACE + d->button_width) + return FALSE; - top_width = name_width + d->button_width + ICON_SPACE; - if (w < top_width) - top_width = MAX (ICON_SPACE + d->button_width, w); + top_width = name_width + d->button_width + ICON_SPACE; + if (w < top_width) + top_width = MAX (ICON_SPACE + d->button_width, w); - decor_get_default_layout (&window_context, top_width, 1, &layout); + decor_get_default_layout (&window_context, top_width, 1, &layout); - if (!d->context || memcmp (&layout, &d->border_layout, sizeof (layout))) - { - *width = layout.width; - *height = layout.height; + if (!d->context || memcmp (&layout, &d->border_layout, sizeof (layout))) + { + *width = layout.width; + *height = layout.height; + d->border_layout = layout; + d->context = &window_context; + d->shadow = border_shadow; + + return TRUE; + } + } + else + { + calc_button_size (d); + + /* _default_win_extents + top height */ + + top_width = name_width + d->button_width + ICON_SPACE; + if (w < top_width) + top_width = MAX (ICON_SPACE + d->button_width, w); + + decor_get_default_layout (&window_context, top_width, 1, &layout); + + *width = d->client_width + _win_extents.left + _win_extents.right + 2; + *height = d->client_height + _win_extents.top + _win_extents.bottom + layout.height - 2; + d->border_layout = layout; - d->context = &window_context; - d->shadow = border_shadow; + d->context = &window_context; + d->shadow = border_shadow; return TRUE; } @@ -3453,22 +3674,36 @@ meta_calc_decoration_size (decor_t *d, decor_get_best_layout (context, w, h, &layout); - if (context != d->context || - memcmp (&layout, &d->border_layout, sizeof (layout))) + if (!d->frame_window) { - *width = layout.width; - *height = layout.height; + if (context != d->context || + memcmp (&layout, &d->border_layout, sizeof (layout))) + { + *width = layout.width; + *height = layout.height; + + d->border_layout = layout; + d->context = context; + d->shadow = shadow; + + meta_calc_button_size (d); + + return TRUE; + } + } + else + { + *width = d->client_width + _win_extents.left + _win_extents.right + 2; + *height = d->client_height + layout.height + _win_extents.top + _win_extents.bottom - 2; d->border_layout = layout; d->context = context; - d->shadow = shadow; meta_calc_button_size (d); return TRUE; } - return FALSE; } #endif @@ -3481,11 +3716,12 @@ update_window_decoration_size (WnckWindow *win) Picture picture; gint width, height; gint w, h, name_width; + gint x, y; Display *xdisplay; xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - wnck_window_get_client_window_geometry (win, NULL, NULL, &w, &h); + wnck_window_get_client_window_geometry (win, &x, &y, &w, &h); name_width = max_window_name_width (win); @@ -3495,272 +3731,48 @@ update_window_decoration_size (WnckWindow *win) return FALSE; } - pixmap = create_pixmap (width, height); - if (!pixmap) - return FALSE; - - buffer_pixmap = create_pixmap (width, height); - if (!buffer_pixmap) - { - g_object_unref (G_OBJECT (pixmap)); - return FALSE; - } - - picture = XRenderCreatePicture (xdisplay, GDK_PIXMAP_XID (buffer_pixmap), - xformat, 0, NULL); - - if (d->pixmap) - g_object_unref (G_OBJECT (d->pixmap)); - - if (d->buffer_pixmap) - g_object_unref (G_OBJECT (d->buffer_pixmap)); - - if (d->gc) - g_object_unref (G_OBJECT (d->gc)); - - if (d->picture) - XRenderFreePicture (xdisplay, d->picture); - - d->pixmap = pixmap; - d->buffer_pixmap = buffer_pixmap; - d->gc = gdk_gc_new (pixmap); - - d->picture = picture; - - d->width = width; - d->height = height; - - d->prop_xid = wnck_window_get_xid (win); - - update_window_decoration_name (win); - - queue_decor_draw (d); - - return TRUE; -} - -static void -add_frame_window (WnckWindow *win, - Window frame) -{ - Display *xdisplay; - XSetWindowAttributes attr; - gulong xid = wnck_window_get_xid (win); - decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); - gint i, j; - - xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - - d->active = wnck_window_is_active (win); - - attr.event_mask = ButtonPressMask | EnterWindowMask | LeaveWindowMask; - attr.override_redirect = TRUE; - gdk_error_trap_push (); - for (i = 0; i < 3; i++) - { - for (j = 0; j < 3; j++) - { - d->event_windows[i][j] = - XCreateWindow (xdisplay, - frame, - 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWEventMask, &attr); - - if (cursor[i][j].cursor) - XDefineCursor (xdisplay, d->event_windows[i][j], - cursor[i][j].cursor); - } - } - - attr.event_mask |= ButtonReleaseMask; - - for (i = 0; i < BUTTON_NUM; i++) - { - d->button_windows[i] = - XCreateWindow (xdisplay, - frame, - 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWEventMask, &attr); - - d->button_states[i] = 0; - } - - gdk_display_sync (gdk_display_get_default ()); - if (!gdk_error_trap_pop ()) - { - if (get_mwm_prop (xid) & (MWM_DECOR_ALL | MWM_DECOR_TITLE)) - d->decorated = TRUE; - - for (i = 0; i < 3; i++) - for (j = 0; j < 3; j++) - g_hash_table_insert (frame_table, - GINT_TO_POINTER (d->event_windows[i][j]), - GINT_TO_POINTER (xid)); - for (i = 0; i < BUTTON_NUM; i++) - g_hash_table_insert (frame_table, - GINT_TO_POINTER (d->button_windows[i]), - GINT_TO_POINTER (xid)); - - update_window_decoration_state (win); - update_window_decoration_actions (win); - update_window_decoration_icon (win); - update_window_decoration_size (win); - - update_event_windows (win); - } + if (d->frame_window) + pixmap = create_pixmap (width, height, gdk_drawable_get_depth (GDK_DRAWABLE (d->frame_window))); else - { - memset (d->event_windows, 0, sizeof (d->event_windows)); - } -} - -static gboolean -update_switcher_window (WnckWindow *win, - Window selected) -{ - decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); - GdkPixmap *pixmap, *buffer_pixmap = NULL; - gint height, width = 0; - WnckWindow *selected_win; - Display *xdisplay; - - xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - - wnck_window_get_client_window_geometry (win, NULL, NULL, &width, NULL); - - decor_get_default_layout (&switcher_context, width, 1, &d->border_layout); - - width = d->border_layout.width; - height = d->border_layout.height; - - d->decorated = FALSE; - d->draw = draw_switcher_decoration; - - if (!d->pixmap && switcher_pixmap) - { - g_object_ref (G_OBJECT (switcher_pixmap)); - d->pixmap = switcher_pixmap; - } - - if (!d->buffer_pixmap && switcher_buffer_pixmap) - { - g_object_ref (G_OBJECT (switcher_buffer_pixmap)); - d->buffer_pixmap = switcher_buffer_pixmap; - } - - if (!d->width) - d->width = switcher_width; - - if (!d->height) - d->height = switcher_height; - - selected_win = wnck_window_get (selected); - if (selected_win) - { - glong name_length; - PangoLayoutLine *line; - const gchar *name; - - if (d->name) - { - g_free (d->name); - d->name = NULL; - } - - name = wnck_window_get_name (selected_win); - if (name && (name_length = strlen (name))) - { - if (!d->layout) - { - d->layout = pango_layout_new (pango_context); - if (d->layout) - pango_layout_set_wrap (d->layout, PANGO_WRAP_CHAR); - } - - if (d->layout) - { - int tw; - - tw = width - switcher_context.left_space - - switcher_context.right_space - 64; - pango_layout_set_auto_dir (d->layout, FALSE); - pango_layout_set_width (d->layout, tw * PANGO_SCALE); - pango_layout_set_text (d->layout, name, name_length); - - line = pango_layout_get_line (d->layout, 0); + pixmap = create_pixmap (width, height, 32); - name_length = line->length; - if (pango_layout_get_line_count (d->layout) > 1) - { - if (name_length < 4) - { - g_object_unref (G_OBJECT (d->layout)); - d->layout = NULL; - } - else - { - d->name = g_strndup (name, name_length); - strcpy (d->name + name_length - 3, "..."); - } - } - else - d->name = g_strndup (name, name_length); - - if (d->layout) - pango_layout_set_text (d->layout, d->name, name_length); - } - } - else if (d->layout) - { - g_object_unref (G_OBJECT (d->layout)); - d->layout = NULL; - } - } + gdk_flush (); - if (selected != switcher_selected_window) + if (!pixmap || gdk_error_trap_pop ()) { - gtk_label_set_text (GTK_LABEL (switcher_label), ""); - if (selected_win && d->name) - gtk_label_set_text (GTK_LABEL (switcher_label), d->name); - switcher_selected_window = selected; + memset (pixmap, 0, sizeof (pixmap)); + return FALSE; } - if (width == d->width && height == d->height) - { - if (!d->gc) - d->gc = gdk_gc_new (d->pixmap); - - if (!d->picture) - d->picture = - XRenderCreatePicture (xdisplay, - GDK_PIXMAP_XID (d->buffer_pixmap), - xformat, 0, NULL); + gdk_error_trap_push (); - queue_decor_draw (d); - return FALSE; - } + if (d->frame_window) + buffer_pixmap = create_pixmap (width, height, gdk_drawable_get_depth (GDK_DRAWABLE (d->frame_window))); + else + buffer_pixmap = create_pixmap (width, height, 32); - pixmap = create_pixmap (width, height); - if (!pixmap) - return FALSE; + gdk_flush (); - buffer_pixmap = create_pixmap (width, height); - if (!buffer_pixmap) + if (!buffer_pixmap || gdk_error_trap_pop ()) { + memset (buffer_pixmap, 0, sizeof (buffer_pixmap)); g_object_unref (G_OBJECT (pixmap)); return FALSE; } - if (switcher_pixmap) - g_object_unref (G_OBJECT (switcher_pixmap)); + if (gdk_drawable_get_depth (GDK_DRAWABLE (buffer_pixmap)) == 32 || + !d->frame_window) + picture = XRenderCreatePicture (xdisplay, + GDK_PIXMAP_XID (buffer_pixmap), + xformat32, 0, NULL); + else + picture = XRenderCreatePicture (xdisplay, + GDK_PIXMAP_XID (buffer_pixmap), + xformat24, 0, NULL); - if (switcher_buffer_pixmap) - g_object_unref (G_OBJECT (switcher_buffer_pixmap)); if (d->pixmap) g_object_unref (G_OBJECT (d->pixmap)); @@ -3774,323 +3786,29 @@ update_switcher_window (WnckWindow *win, if (d->picture) XRenderFreePicture (xdisplay, d->picture); - switcher_pixmap = pixmap; - switcher_buffer_pixmap = buffer_pixmap; - - switcher_width = width; - switcher_height = height; - - g_object_ref (G_OBJECT (pixmap)); - g_object_ref (G_OBJECT (buffer_pixmap)); d->pixmap = pixmap; d->buffer_pixmap = buffer_pixmap; d->gc = gdk_gc_new (pixmap); - d->picture = XRenderCreatePicture (xdisplay, GDK_PIXMAP_XID (buffer_pixmap), - xformat, 0, NULL); + d->picture = picture; d->width = width; d->height = height; d->prop_xid = wnck_window_get_xid (win); + update_window_decoration_name (win); + queue_decor_draw (d); return TRUE; } static void -remove_frame_window (WnckWindow *win) -{ - decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); - Display *xdisplay; - - xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - - if (d->pixmap) - { - g_object_unref (G_OBJECT (d->pixmap)); - d->pixmap = NULL; - } - - if (d->buffer_pixmap) - { - g_object_unref (G_OBJECT (d->buffer_pixmap)); - d->buffer_pixmap = NULL; - } - - if (d->gc) - { - g_object_unref (G_OBJECT (d->gc)); - d->gc = NULL; - } - - if (d->picture) - { - XRenderFreePicture (xdisplay, d->picture); - d->picture = 0; - } - - if (d->name) - { - g_free (d->name); - d->name = NULL; - } - - if (d->layout) - { - g_object_unref (G_OBJECT (d->layout)); - d->layout = NULL; - } - - if (d->icon) - { - cairo_pattern_destroy (d->icon); - d->icon = NULL; - } - - if (d->icon_pixmap) - { - g_object_unref (G_OBJECT (d->icon_pixmap)); - d->icon_pixmap = NULL; - } - - if (d->icon_pixbuf) - { - g_object_unref (G_OBJECT (d->icon_pixbuf)); - d->icon_pixbuf = NULL; - } - - if (d->force_quit_dialog) - { - GtkWidget *dialog = d->force_quit_dialog; - - d->force_quit_dialog = NULL; - gtk_widget_destroy (dialog); - } - - d->width = 0; - d->height = 0; - - d->decorated = FALSE; - - d->state = 0; - d->actions = 0; - - d->context = NULL; - d->shadow = NULL; - - draw_list = g_slist_remove (draw_list, d); -} - -static void -window_name_changed (WnckWindow *win) -{ - decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); - - if (d->decorated) - { - if (!update_window_decoration_size (win)) - queue_decor_draw (d); - } -} - -static void -window_geometry_changed (WnckWindow *win) -{ - decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); - - if (d->decorated) - { - int width, height; - - wnck_window_get_client_window_geometry (win, NULL, NULL, &width, - &height); - - if (width != d->client_width || height != d->client_height) - { - d->client_width = width; - d->client_height = height; - - update_window_decoration_size (win); - update_event_windows (win); - } - } -} - -static void -window_icon_changed (WnckWindow *win) -{ - decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); - - if (d->decorated) - { - update_window_decoration_icon (win); - queue_decor_draw (d); - } -} - -static void -window_state_changed (WnckWindow *win) -{ - decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); - - if (d->decorated) - { - update_window_decoration_state (win); - if (!update_window_decoration_size (win)) - queue_decor_draw (d); - - update_event_windows (win); - } -} - -static void -window_actions_changed (WnckWindow *win) -{ - decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); - - if (d->decorated) - { - update_window_decoration_actions (win); - if (!update_window_decoration_size (win)) - queue_decor_draw (d); - - update_event_windows (win); - } -} - -static void -connect_window (WnckWindow *win) -{ - g_signal_connect_object (win, "name_changed", - G_CALLBACK (window_name_changed), - 0, 0); - g_signal_connect_object (win, "geometry_changed", - G_CALLBACK (window_geometry_changed), - 0, 0); - g_signal_connect_object (win, "icon_changed", - G_CALLBACK (window_icon_changed), - 0, 0); - g_signal_connect_object (win, "state_changed", - G_CALLBACK (window_state_changed), - 0, 0); - g_signal_connect_object (win, "actions_changed", - G_CALLBACK (window_actions_changed), - 0, 0); -} - -static void -active_window_changed (WnckScreen *screen) -{ - WnckWindow *win; - decor_t *d; - - win = wnck_screen_get_previously_active_window (screen); - if (win) - { - d = g_object_get_data (G_OBJECT (win), "decor"); - if (d && d->pixmap) - { - d->active = wnck_window_is_active (win); - queue_decor_draw (d); - } - } - - win = wnck_screen_get_active_window (screen); - if (win) - { - d = g_object_get_data (G_OBJECT (win), "decor"); - if (d && d->pixmap) - { - d->active = wnck_window_is_active (win); - queue_decor_draw (d); - } - } -} - -static void -window_opened (WnckScreen *screen, - WnckWindow *win) -{ - decor_t *d; - Window window; - gulong xid; - - d = calloc (1, sizeof (decor_t)); - if (!d) - return; - - wnck_window_get_client_window_geometry (win, NULL, NULL, - &d->client_width, - &d->client_height); - - d->draw = theme_draw_window_decoration; - - g_object_set_data (G_OBJECT (win), "decor", d); - - connect_window (win); - - xid = wnck_window_get_xid (win); - - if (get_window_prop (xid, select_window_atom, &window)) - { - d->prop_xid = wnck_window_get_xid (win); - update_switcher_window (win, window); - } - else if (get_window_prop (xid, frame_window_atom, &window)) - { - add_frame_window (win, window); - } -} - -static void -window_closed (WnckScreen *screen, - WnckWindow *win) -{ - Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); - - remove_frame_window (win); - - g_object_set_data (G_OBJECT (win), "decor", NULL); - - gdk_error_trap_push (); - XDeleteProperty (xdisplay, wnck_window_get_xid (win), win_decor_atom); - gdk_display_sync (gdk_display_get_default ()); - gdk_error_trap_pop (); - - g_free (d); -} - -static void -connect_screen (WnckScreen *screen) -{ - GList *windows; - - g_signal_connect_object (G_OBJECT (screen), "active_window_changed", - G_CALLBACK (active_window_changed), - 0, 0); - g_signal_connect_object (G_OBJECT (screen), "window_opened", - G_CALLBACK (window_opened), - 0, 0); - g_signal_connect_object (G_OBJECT (screen), "window_closed", - G_CALLBACK (window_closed), - 0, 0); - - windows = wnck_screen_get_windows (screen); - while (windows != NULL) - { - window_opened (screen, windows->data); - windows = windows->next; - } -} - -static void move_resize_window (WnckWindow *win, int direction, - XEvent *xevent) + decor_event *gtkwd_event) { Display *xdisplay; GdkDisplay *gdkdisplay; @@ -4121,14 +3839,14 @@ move_resize_window (WnckWindow *win, ev.xclient.message_type = wm_move_resize_atom; ev.xclient.format = 32; - ev.xclient.data.l[0] = xevent->xbutton.x_root; - ev.xclient.data.l[1] = xevent->xbutton.y_root; + ev.xclient.data.l[0] = gtkwd_event->x_root; + ev.xclient.data.l[1] = gtkwd_event->y_root; ev.xclient.data.l[2] = direction; - ev.xclient.data.l[3] = xevent->xbutton.button; + ev.xclient.data.l[3] = gtkwd_event->button; ev.xclient.data.l[4] = 1; - XUngrabPointer (xdisplay, xevent->xbutton.time); - XUngrabKeyboard (xdisplay, xevent->xbutton.time); + XUngrabPointer (xdisplay, gtkwd_event->time); + XUngrabKeyboard (xdisplay, gtkwd_event->time); XSendEvent (xdisplay, xroot, FALSE, SubstructureRedirectMask | SubstructureNotifyMask, @@ -4340,32 +4058,36 @@ create_tooltip_window (void) static void handle_tooltip_event (WnckWindow *win, - XEvent *xevent, + decor_event *gtkwd_event, + decor_event_type gtkwd_type, guint state, const char *tip) { - switch (xevent->type) { - case ButtonPress: + switch (gtkwd_type) { + case GButtonPress: hide_tooltip (); break; - case ButtonRelease: + case GButtonRelease: break; - case EnterNotify: + case GEnterNotify: if (!(state & PRESSED_EVENT_WINDOW)) { if (wnck_window_is_active (win)) tooltip_start_delay (tip); } break; - case LeaveNotify: + case GLeaveNotify: hide_tooltip (); break; + default: + break; } } static void common_button_event (WnckWindow *win, - XEvent *xevent, + decor_event *gtkwd_event, + decor_event_type gtkwd_type, int button, int max, char *tooltip) @@ -4373,79 +4095,98 @@ common_button_event (WnckWindow *win, decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); guint state = d->button_states[button]; - handle_tooltip_event (win, xevent, state, tooltip); + handle_tooltip_event (win, gtkwd_event, gtkwd_type, state, tooltip); - switch (xevent->type) { - case ButtonPress: - if (xevent->xbutton.button <= max) + if (d->frame_window && gtkwd_type == GEnterNotify) + { + GdkCursor* cursor; + cursor = gdk_cursor_new (GDK_LEFT_PTR); + gdk_window_set_cursor (d->frame_window, cursor); + gdk_cursor_unref (cursor); + } + + switch (gtkwd_type) { + case GButtonPress: + if (gtkwd_event->button <= max) d->button_states[button] |= PRESSED_EVENT_WINDOW; break; - case ButtonRelease: - if (xevent->xbutton.button <= max) + case GButtonRelease: + if (gtkwd_event->button <= max) d->button_states[button] &= ~PRESSED_EVENT_WINDOW; break; - case EnterNotify: + case GEnterNotify: d->button_states[button] |= IN_EVENT_WINDOW; break; - case LeaveNotify: + case GLeaveNotify: d->button_states[button] &= ~IN_EVENT_WINDOW; break; + default: + break; } - + if (state != d->button_states[button]) + { queue_decor_draw (d); + } } #define BUTTON_EVENT_ACTION_STATE (PRESSED_EVENT_WINDOW | IN_EVENT_WINDOW) static void close_button_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); guint state = d->button_states[BUTTON_CLOSE]; - common_button_event (win, xevent, BUTTON_CLOSE, 1, _("Close Window")); + common_button_event (win, gtkwd_event, gtkwd_type, + BUTTON_CLOSE, 1, _("Close Window")); - switch (xevent->type) { - case ButtonRelease: - if (xevent->xbutton.button == 1) + switch (gtkwd_type) { + case GButtonRelease: + if (gtkwd_event->button == 1) { if (state == BUTTON_EVENT_ACTION_STATE) - wnck_window_close (win, xevent->xbutton.time); + { + wnck_window_close (win, gtkwd_event->time); + } } break; + default: + break; } } static void max_button_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); guint state = d->button_states[BUTTON_MAX]; if (wnck_window_is_maximized (win)) - common_button_event (win, xevent, BUTTON_MAX, + common_button_event (win, gtkwd_event, gtkwd_type, BUTTON_MAX, 3, _("Unmaximize Window")); else - common_button_event (win, xevent, BUTTON_MAX, + common_button_event (win, gtkwd_event, gtkwd_type, BUTTON_MAX, 3, _("Maximize Window")); - switch (xevent->type) { - case ButtonRelease: - if (xevent->xbutton.button <= 3) + switch (gtkwd_type) { + case GButtonRelease: + if (gtkwd_event->button <= 3) { if (state == BUTTON_EVENT_ACTION_STATE) { - if (xevent->xbutton.button == 2) + if (gtkwd_event->button == 2) { if (wnck_window_is_maximized_vertically (win)) wnck_window_unmaximize_vertically (win); else wnck_window_maximize_vertically (win); } - else if (xevent->xbutton.button == 3) + else if (gtkwd_event->button == 3) { if (wnck_window_is_maximized_horizontally (win)) wnck_window_unmaximize_horizontally (win); @@ -4462,26 +4203,32 @@ max_button_event (WnckWindow *win, } } break; + default: + break; } } static void min_button_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); guint state = d->button_states[BUTTON_MIN]; - common_button_event (win, xevent, BUTTON_MIN, 1, _("Minimize Window")); + common_button_event (win, gtkwd_event, gtkwd_type, + BUTTON_MIN, 1, _("Minimize Window")); - switch (xevent->type) { - case ButtonRelease: - if (xevent->xbutton.button == 1) + switch (gtkwd_type) { + case GButtonRelease: + if (gtkwd_event->button == 1) { if (state == BUTTON_EVENT_ACTION_STATE) wnck_window_minimize (win); } break; + default: + break; } } @@ -4595,52 +4342,63 @@ action_menu_map (WnckWindow *win, static void menu_button_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { - common_button_event (win, xevent, BUTTON_MENU, 1, _("Window Menu")); - switch (xevent->type) { - case ButtonPress: - if (xevent->xbutton.button == 1) + common_button_event (win, gtkwd_event, gtkwd_type, + BUTTON_MENU, 1, _("Window Menu")); + + switch (gtkwd_type) { + case GButtonPress: + if (gtkwd_event->button == 1) action_menu_map (win, - xevent->xbutton.button, - xevent->xbutton.time); + gtkwd_event->button, + gtkwd_event->time); + break; + default: break; } } static void shade_button_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); guint state = d->button_states[BUTTON_SHADE]; - common_button_event (win, xevent, BUTTON_SHADE, 1, _("Shade")); + common_button_event (win, gtkwd_event, gtkwd_type, + BUTTON_SHADE, 1, _("Shade")); - switch (xevent->type) { - case ButtonRelease: - if (xevent->xbutton.button == 1) + switch (gtkwd_type) { + case GButtonRelease: + if (gtkwd_event->button == 1) { if (state == BUTTON_EVENT_ACTION_STATE) wnck_window_shade (win); } break; + default: + break; } } static void above_button_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); guint state = d->button_states[BUTTON_ABOVE]; - common_button_event (win, xevent, BUTTON_ABOVE, 1, _("Make Above")); + common_button_event (win, gtkwd_event, gtkwd_type, + BUTTON_ABOVE, 1, _("Make Above")); - switch (xevent->type) { - case ButtonRelease: - if (xevent->xbutton.button == 1) + switch (gtkwd_type) { + case GButtonRelease: + if (gtkwd_event->button == 1) { if (state == BUTTON_EVENT_ACTION_STATE) { @@ -4652,61 +4410,73 @@ above_button_event (WnckWindow *win, } } break; + default: + break; } } static void stick_button_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); guint state = d->button_states[BUTTON_STICK]; - common_button_event (win, xevent, BUTTON_STICK, 1, _("Stick")); + common_button_event (win, gtkwd_event, gtkwd_type, + BUTTON_STICK, 1, _("Stick")); - switch (xevent->type) { - case ButtonRelease: - if (xevent->xbutton.button == 1) + switch (gtkwd_type) { + case GButtonRelease: + if (gtkwd_event->button == 1) { if (state == BUTTON_EVENT_ACTION_STATE) wnck_window_stick (win); } break; + default: + break; } } static void unshade_button_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); guint state = d->button_states[BUTTON_UNSHADE]; - common_button_event (win, xevent, BUTTON_UNSHADE, 1, _("Unshade")); + common_button_event (win, gtkwd_event, gtkwd_type, + BUTTON_UNSHADE, 1, _("Unshade")); - switch (xevent->type) { - case ButtonRelease: - if (xevent->xbutton.button == 1) + switch (gtkwd_type) { + case GButtonRelease: + if (gtkwd_event->button == 1) { if (state == BUTTON_EVENT_ACTION_STATE) wnck_window_unshade (win); } break; + default: + break; } } static void unabove_button_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); guint state = d->button_states[BUTTON_UNABOVE]; - common_button_event (win, xevent, BUTTON_UNABOVE, 1, _("Unmake Above")); + common_button_event (win, gtkwd_event, gtkwd_type, + BUTTON_UNABOVE, 1, _("Unmake Above")); - switch (xevent->type) { - case ButtonRelease: - if (xevent->xbutton.button == 1) + switch (gtkwd_type) { + case GButtonRelease: + if (gtkwd_event->button == 1) { if (state == BUTTON_EVENT_ACTION_STATE) { @@ -4718,33 +4488,39 @@ unabove_button_event (WnckWindow *win, } } break; + default: + break; } } static void unstick_button_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); guint state = d->button_states[BUTTON_UNSTICK]; - common_button_event (win, xevent, BUTTON_UNSTICK, 1, _("Unstick")); + common_button_event (win, gtkwd_event, gtkwd_type, + BUTTON_UNSTICK, 1, _("Unstick")); - switch (xevent->type) { - case ButtonRelease: - if (xevent->xbutton.button == 1) + switch (gtkwd_type) { + case GButtonRelease: + if (gtkwd_event->button == 1) { if (state == BUTTON_EVENT_ACTION_STATE) wnck_window_unstick (win); } break; + default: + break; } } static void handle_title_button_event (WnckWindow *win, int action, - XButtonEvent *event) + decor_event *gtkwd_event) { switch (action) { case CLICK_ACTION_SHADE: @@ -4770,7 +4546,7 @@ handle_title_button_event (WnckWindow *win, restack_window (win, Below); break; case CLICK_ACTION_MENU: - action_menu_map (win, event->button, event->time); + action_menu_map (win, gtkwd_event->button, gtkwd_event->time); break; } } @@ -4812,7 +4588,8 @@ dist (double x1, double y1, static void title_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { static int last_button_num = 0; static Window last_button_xwindow = None; @@ -4820,19 +4597,29 @@ title_event (WnckWindow *win, static int last_button_x = 0; static int last_button_y = 0; - if (xevent->type != ButtonPress) + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + + if (d->frame_window && gtkwd_type == GEnterNotify) + { + GdkCursor* cursor; + cursor = gdk_cursor_new (GDK_LEFT_PTR); + gdk_window_set_cursor (d->frame_window, cursor); + gdk_cursor_unref (cursor); + } + + if (gtkwd_type != GButtonPress) return; - if (xevent->xbutton.button == 1) + if (gtkwd_event->button == 1) { - if (xevent->xbutton.button == last_button_num && - xevent->xbutton.window == last_button_xwindow && - xevent->xbutton.time < last_button_time + double_click_timeout && - dist (xevent->xbutton.x, xevent->xbutton.y, + if (gtkwd_event->button == last_button_num && + gtkwd_event->window == last_button_xwindow && + gtkwd_event->time < last_button_time + double_click_timeout && + dist (gtkwd_event->x, gtkwd_event->y, last_button_x, last_button_y) < DOUBLE_CLICK_DISTANCE) { handle_title_button_event (win, double_click_action, - &xevent->xbutton); + gtkwd_event); last_button_num = 0; last_button_xwindow = None; @@ -4842,115 +4629,1346 @@ title_event (WnckWindow *win, } else { - last_button_num = xevent->xbutton.button; - last_button_xwindow = xevent->xbutton.window; - last_button_time = xevent->xbutton.time; - last_button_x = xevent->xbutton.x; - last_button_y = xevent->xbutton.y; + last_button_num = gtkwd_event->button; + last_button_xwindow = gtkwd_event->window; + last_button_time = gtkwd_event->time; + last_button_x = gtkwd_event->x; + last_button_y = gtkwd_event->y; restack_window (win, Above); - move_resize_window (win, WM_MOVERESIZE_MOVE, xevent); + move_resize_window (win, WM_MOVERESIZE_MOVE, gtkwd_event); } } - else if (xevent->xbutton.button == 2) + else if (gtkwd_event->button == 2) { handle_title_button_event (win, middle_click_action, - &xevent->xbutton); + gtkwd_event); } - else if (xevent->xbutton.button == 3) + else if (gtkwd_event->button == 3) { handle_title_button_event (win, right_click_action, - &xevent->xbutton); + gtkwd_event); } - else if (xevent->xbutton.button == 4 || - xevent->xbutton.button == 5) + else if (gtkwd_event->button == 4 || + gtkwd_event->button == 5) { - handle_mouse_wheel_title_event (win, xevent->xbutton.button); + handle_mouse_wheel_title_event (win, gtkwd_event->button); } } static void frame_common_event (WnckWindow *win, int direction, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { - if (xevent->type != ButtonPress) + + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + + + if (d->frame_window && gtkwd_type == GEnterNotify) + { + GdkCursor *cursor = NULL; + + switch (direction) + { + case WM_MOVERESIZE_SIZE_TOPLEFT: + cursor = gdk_cursor_new (GDK_TOP_LEFT_CORNER); + break; + case WM_MOVERESIZE_SIZE_LEFT: + cursor = gdk_cursor_new (GDK_LEFT_SIDE); + break; + case WM_MOVERESIZE_SIZE_BOTTOMLEFT: + cursor = gdk_cursor_new (GDK_BOTTOM_LEFT_CORNER); + break; + case WM_MOVERESIZE_SIZE_BOTTOM: + cursor = gdk_cursor_new (GDK_BOTTOM_SIDE); + break; + case WM_MOVERESIZE_SIZE_BOTTOMRIGHT: + cursor = gdk_cursor_new (GDK_BOTTOM_RIGHT_CORNER); + break; + case WM_MOVERESIZE_SIZE_RIGHT: + cursor = gdk_cursor_new (GDK_RIGHT_SIDE); + break; + case WM_MOVERESIZE_SIZE_TOPRIGHT: + cursor = gdk_cursor_new (GDK_TOP_RIGHT_CORNER); + break; + case WM_MOVERESIZE_SIZE_TOP: + cursor = gdk_cursor_new (GDK_TOP_SIDE); + break; + default: + break; + } + + if (cursor) + { + gdk_window_set_cursor (d->frame_window, cursor); + gdk_cursor_unref (cursor); + } + } + + if (gtkwd_type != GButtonPress) return; - switch (xevent->xbutton.button) { + switch (gtkwd_event->button) { case 1: - move_resize_window (win, direction, xevent); + move_resize_window (win, direction, gtkwd_event); restack_window (win, Above); break; case 2: handle_title_button_event (win, middle_click_action, - &xevent->xbutton); + gtkwd_event); break; case 3: handle_title_button_event (win, right_click_action, - &xevent->xbutton); + gtkwd_event); break; } } static void top_left_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { - frame_common_event (win, WM_MOVERESIZE_SIZE_TOPLEFT, xevent); + frame_common_event (win, WM_MOVERESIZE_SIZE_TOPLEFT, gtkwd_event, gtkwd_type); } static void top_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { - frame_common_event (win, WM_MOVERESIZE_SIZE_TOP, xevent); + frame_common_event (win, WM_MOVERESIZE_SIZE_TOP, gtkwd_event, gtkwd_type); } static void top_right_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { - frame_common_event (win, WM_MOVERESIZE_SIZE_TOPRIGHT, xevent); + + frame_common_event (win, WM_MOVERESIZE_SIZE_TOPRIGHT, gtkwd_event, gtkwd_type); } static void left_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { - frame_common_event (win, WM_MOVERESIZE_SIZE_LEFT, xevent); + + frame_common_event (win, WM_MOVERESIZE_SIZE_LEFT, gtkwd_event, gtkwd_type); } static void right_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { - frame_common_event (win, WM_MOVERESIZE_SIZE_RIGHT, xevent); + + frame_common_event (win, WM_MOVERESIZE_SIZE_RIGHT, gtkwd_event, gtkwd_type); } static void bottom_left_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { - frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOMLEFT, xevent); + + frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOMLEFT, gtkwd_event, gtkwd_type); } static void bottom_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { - frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOM, xevent); + + frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOM, gtkwd_event, gtkwd_type); } static void bottom_right_event (WnckWindow *win, - XEvent *xevent) + decor_event *gtkwd_event, + decor_event_type gtkwd_type) { - frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOMRIGHT, xevent); + + frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOMRIGHT, gtkwd_event, gtkwd_type); +} + +void +frame_window_realized (GtkWidget *widget, + gpointer data) +{ + decor_t *d = (decor_t *) data; + + if (d) + { + GdkWindow *gdk_frame_window = gtk_widget_get_window (d->decor_window); + gdk_window_reparent (gdk_frame_window, d->frame_window, 0, 0); + gdk_window_lower (gdk_frame_window); + + } } static void +frame_handle_button_press (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + decor_t *d = (decor_t *) user_data; + + if (d) + { + /* Check to see where the event happened and fill out an appropriate + * struct + */ + + int i, j; + Bool found = FALSE; + Bool event_area = FALSE; + Bool exit = FALSE; + + for (i = 0; i < BUTTON_NUM; i++) + { + /* Hit */ + if (event->x >= d->button_window_pos[i].x1 && + event->x <= d->button_window_pos[i].x2 && + event->y >= d->button_window_pos[i].y1 && + event->y <= d->button_window_pos[i].y2) + { + found = TRUE; + + break; + } + } + + if (!found) + { + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + if (event->x >= d->event_window_pos[i][j].x1 && + event->x <= d->event_window_pos[i][j].x2 && + event->y >= d->event_window_pos[i][j].y1 && + event->y <= d->event_window_pos[i][j].y2) + { + found = TRUE; + event_area = TRUE; + + exit = TRUE; + + break; + } + } + + if (exit) + break; + } + } + + if (found) + { + static event_callback callback[3][3] = { + { top_left_event, top_event, top_right_event }, + { left_event, title_event, right_event }, + { bottom_left_event, bottom_event, bottom_right_event } + }; + static event_callback button_callback[BUTTON_NUM] = { + close_button_event, + max_button_event, + min_button_event, + menu_button_event, + shade_button_event, + above_button_event, + stick_button_event, + unshade_button_event, + unabove_button_event, + unstick_button_event + }; + + if (d->decorated) + { + decor_event gtkwd_event; + decor_event_type gtkwd_type; + + gtkwd_type = GButtonPress; + + gtkwd_event.window = GDK_WINDOW_XID (d->frame_window); + gtkwd_event.button = event->button; + gtkwd_event.x = event->x; + gtkwd_event.y = event->y; + gtkwd_event.x_root = event->x_root; + gtkwd_event.y_root = event->y_root; + gtkwd_event.time = event->time; + + if (event_area) + (*(callback[i][j])) (d->win, >kwd_event, gtkwd_type); + else + { + (*button_callback[i]) (d->win, >kwd_event, gtkwd_type); + } + } + } + } +} + +static void +frame_handle_button_release (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + decor_t *d = (decor_t *) user_data; + + if (d) + { + /* Check to see where the event happened and fill out an appropriate + * struct + */ + + int i, j; + Bool found = FALSE; + Bool event_area = FALSE; + Bool exit = FALSE; + + for (i = 0; i < BUTTON_NUM; i++) + { + /* Hit */ + if (event->x >= d->button_window_pos[i].x1 && + event->x <= d->button_window_pos[i].x2 && + event->y >= d->button_window_pos[i].y1 && + event->y <= d->button_window_pos[i].y2) + { + found = TRUE; + + break; + } + } + + if (!found) + { + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + if (event->x >= d->event_window_pos[i][j].x1 && + event->x <= d->event_window_pos[i][j].x2 && + event->y >= d->event_window_pos[i][j].y1 && + event->y <= d->event_window_pos[i][j].y2) + { + found = TRUE; + event_area = TRUE; + + exit = TRUE; + + break; + } + } + + if (exit) + break; + + } + } + + if (found) + { + static event_callback callback[3][3] = { + { top_left_event, top_event, top_right_event }, + { left_event, title_event, right_event }, + { bottom_left_event, bottom_event, bottom_right_event } + }; + static event_callback button_callback[BUTTON_NUM] = { + close_button_event, + max_button_event, + min_button_event, + menu_button_event, + shade_button_event, + above_button_event, + stick_button_event, + unshade_button_event, + unabove_button_event, + unstick_button_event + }; + + if (d->decorated) + { + decor_event gtkwd_event; + decor_event_type gtkwd_type; + + gtkwd_type = GButtonRelease; + + gtkwd_event.window = GDK_WINDOW_XID (d->frame_window); + gtkwd_event.button = event->button; + gtkwd_event.x = event->x; + gtkwd_event.y = event->y; + gtkwd_event.x_root = event->x_root; + gtkwd_event.y_root = event->y_root; + gtkwd_event.time = event->time; + + if (event_area) + (*callback[i][j]) (d->win, >kwd_event, gtkwd_type); + else + { + (*button_callback[i]) (d->win, >kwd_event, gtkwd_type); + } + } + } + } +} + +static void +frame_handle_motion (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data) +{ + decor_t *d = (decor_t *) user_data; + + static event_callback callback[3][3] = { + { top_left_event, top_event, top_right_event }, + { left_event, title_event, right_event }, + { bottom_left_event, bottom_event, bottom_right_event } + }; + static event_callback button_callback[BUTTON_NUM] = { + close_button_event, + max_button_event, + min_button_event, + menu_button_event, + shade_button_event, + above_button_event, + stick_button_event, + unshade_button_event, + unabove_button_event, + unstick_button_event + }; + + if (d) + { + /* Check to see where the event happened and fill out an appropriate + * struct + */ + + int i, j; + Bool found = FALSE; + Bool event_area = FALSE; + Bool send_enter = FALSE; + Bool send_leave = FALSE; + Bool exit = FALSE; + + /* Check buttons */ + + for (i = 0; i < BUTTON_NUM; i++) + { + /* Hit */ + if (event->x >= d->button_window_pos[i].x1 && + event->x <= d->button_window_pos[i].x2 && + event->y >= d->button_window_pos[i].y1 && + event->y <= d->button_window_pos[i].y2) + { + found = TRUE; + + if (d->last_pos_entered != &(d->button_window_pos[i])) + { + send_enter = TRUE; + if (d->last_pos_entered) + { + send_leave = TRUE; + } + } + + break; + } + } + + /* Check event windows */ + + exit = FALSE; + + if (!found) + { + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + if (event->x >= d->event_window_pos[i][j].x1 && + event->x <= d->event_window_pos[i][j].x2 && + event->y >= d->event_window_pos[i][j].y1 && + event->y <= d->event_window_pos[i][j].y2) + { + found = TRUE; + event_area = TRUE; + + if (d->last_pos_entered != &(d->event_window_pos[i][j])) + { + send_enter = TRUE; + if (d->last_pos_entered) + { + send_leave = TRUE; + } + } + + exit = TRUE; + + break; + } + } + + if (exit) + break; + } + } + + if (found) + { + if (d->decorated) + { + decor_event gtkwd_event; + decor_event_type gtkwd_type; + + gtkwd_event.window = GDK_WINDOW_XID (d->frame_window); + gtkwd_event.x = event->x; + gtkwd_event.y = event->y; + gtkwd_event.x_root = event->x_root; + gtkwd_event.y_root = event->y_root; + gtkwd_event.time = event->time; + + if (send_enter) + { + gtkwd_type = GEnterNotify; + + if (event_area) + (*callback[i][j]) (d->win, >kwd_event, gtkwd_type); + else + { + (*button_callback[i]) (d->win, >kwd_event, gtkwd_type); + } + + } + + if (send_leave) + { + guint k, l; + Bool l_event_area = FALSE; + Bool l_found = FALSE; + + gtkwd_type = GLeaveNotify; + + for (k = 0; k < 3; k++) + { + if (d->last_pos_entered == &(d->button_window_pos[k])) + { + l_found = TRUE; + break; + } + } + + exit = FALSE; + + if (!l_found) + { + for (k = 0; k < 3; k++) + { + for (l = 0; l < 3; l++) + { + if (d->last_pos_entered == &(d->event_window_pos[k][l])) + { + l_found = TRUE; + l_event_area = TRUE; + + exit = TRUE; + + break; + } + } + + if (exit) + break; + } + } + + if (l_found) + { + if (l_event_area) + (*callback[k][l]) (d->win, >kwd_event, gtkwd_type); + else + { + (*button_callback[k]) (d->win, >kwd_event, gtkwd_type); + } + } + } + + if (send_enter) + { + if (event_area) + d->last_pos_entered = &d->event_window_pos[i][j]; + else + d->last_pos_entered = &d->button_window_pos[i]; + } + } + } + else if (d->last_pos_entered && d->decorated) + { + /* We are not in an event / button window but last_pos_entered + * is still set, so send a GLeaveNotify to last_pos_entered + * and set it to NULL + */ + + decor_event gtkwd_event; + decor_event_type gtkwd_type; + + gtkwd_event.window = GDK_WINDOW_XID (d->frame_window); + gtkwd_event.x = event->x; + gtkwd_event.y = event->y; + gtkwd_event.x_root = event->x_root; + gtkwd_event.y_root = event->y_root; + gtkwd_event.time = event->time; + + guint k, l; + Bool l_event_area = FALSE; + Bool l_found = FALSE; + + gtkwd_type = GLeaveNotify; + + for (k = 0; k < 3; k++) + { + if (d->last_pos_entered == &(d->button_window_pos[k])) + { + l_found = TRUE; + break; + } + } + + exit = FALSE; + + if (!l_found) + { + for (k = 0; k < 3; k++) + { + for (l = 0; l < 3; l++) + { + if (d->last_pos_entered == &(d->event_window_pos[k][l])) + { + l_found = TRUE; + l_event_area = TRUE; + + exit = TRUE; + + break; + } + } + + if (exit) + break; + + } + } + + if (l_found) + { + if (l_event_area) + (*callback[k][l]) (d->win, >kwd_event, gtkwd_type); + else + { + (*button_callback[k]) (d->win, >kwd_event, gtkwd_type); + } + } + + d->last_pos_entered = NULL; + } + + } +} + +static void +window_name_changed (WnckWindow *win) +{ + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + + if (d->decorated) + { + if (!update_window_decoration_size (win)) + queue_decor_draw (d); + } +} + +static void +window_geometry_changed (WnckWindow *win) +{ + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + + if (d->decorated) + { + int width, height; + + wnck_window_get_client_window_geometry (win, NULL, NULL, &width, + &height); + + if (width != d->client_width || height != d->client_height) + { + d->client_width = width; + d->client_height = height; + + update_window_decoration_size (win); + update_event_windows (win); + } + } +} + +static void +window_icon_changed (WnckWindow *win) +{ + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + + if (d->decorated) + { + update_window_decoration_icon (win); + queue_decor_draw (d); + } +} + +static void +window_state_changed (WnckWindow *win) +{ + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + + if (d->decorated) + { + update_window_decoration_state (win); + if (!update_window_decoration_size (win)) + queue_decor_draw (d); + + update_event_windows (win); + } +} + +static void +window_actions_changed (WnckWindow *win) +{ + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + + if (d->decorated) + { + update_window_decoration_actions (win); + if (!update_window_decoration_size (win)) + queue_decor_draw (d); + + update_event_windows (win); + } +} + +static void +connect_window (WnckWindow *win) +{ + g_signal_connect_object (win, "name_changed", + G_CALLBACK (window_name_changed), + 0, 0); + g_signal_connect_object (win, "geometry_changed", + G_CALLBACK (window_geometry_changed), + 0, 0); + g_signal_connect_object (win, "icon_changed", + G_CALLBACK (window_icon_changed), + 0, 0); + g_signal_connect_object (win, "state_changed", + G_CALLBACK (window_state_changed), + 0, 0); + g_signal_connect_object (win, "actions_changed", + G_CALLBACK (window_actions_changed), + 0, 0); +} + +static void +add_frame_window (WnckWindow *win, + Window frame, + Bool mode) +{ + Display *xdisplay; + XSetWindowAttributes attr; + gulong xid = wnck_window_get_xid (win); + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + gint i, j; + + xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + + /* If we have already done this, there is no need to do it again, except + * if the property changed. + * + * The reason this check is here is because sometimes the PropertyNotify X + * event can come a bit after the property on the window is actually set + * which might result in this function being called twice - once by + * wnck through window_opened and once through our X event handler + * event_filter_func + */ + + if (d->created) + { + if ((mode && d->frame_window) || (!mode && !d->frame_window)) + { + return; + } + } + + d->active = wnck_window_is_active (win); + d->win = win; + d->last_pos_entered = NULL; + + attr.event_mask = ButtonPressMask | EnterWindowMask | LeaveWindowMask | + ExposureMask; + attr.override_redirect = TRUE; + + gdk_error_trap_push (); + + if (mode) + { + GdkScreen *screen = gdk_display_get_default_screen (gdk_display_get_default ()); + GdkColormap *colormap; + + d->frame_window = create_gdk_window (frame); + d->decor_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + if (gdk_drawable_get_depth (GDK_DRAWABLE (d->frame_window)) == 24) + colormap = gdk_screen_get_rgb_colormap (screen); + else if (gdk_drawable_get_depth (GDK_DRAWABLE (d->frame_window)) == 32) + colormap = gdk_screen_get_rgba_colormap (screen); + + gtk_widget_set_colormap (d->decor_window, colormap); + + d->decor_image = gtk_image_new (); + + gtk_widget_set_colormap (d->decor_image, colormap); + + d->decor_event_box = gtk_event_box_new (); + gtk_event_box_set_visible_window (GTK_EVENT_BOX (d->decor_event_box), FALSE); + gtk_widget_set_events (d->decor_event_box, GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK); + + g_signal_connect (G_OBJECT (d->decor_event_box), "button-press-event", + G_CALLBACK (frame_handle_button_press), + (gpointer) (d)); + + g_signal_connect (G_OBJECT (d->decor_event_box), "button-release-event", + G_CALLBACK (frame_handle_button_release), + (gpointer) (d)); + + g_signal_connect (G_OBJECT (d->decor_event_box), "motion-notify-event", + G_CALLBACK (frame_handle_motion), + (gpointer) (d)); + + gtk_container_add (GTK_CONTAINER (d->decor_event_box), d->decor_image); + gtk_event_box_set_above_child (GTK_EVENT_BOX (d->decor_event_box), TRUE); + gtk_widget_show_all (d->decor_event_box); + gtk_window_set_decorated (GTK_WINDOW (d->decor_window), FALSE); + gtk_window_set_default_size (GTK_WINDOW (d->decor_window), 1000, 1000); + gtk_container_add (GTK_CONTAINER (d->decor_window), d->decor_event_box); + + /* Assumed realization happens here */ + + g_signal_connect (G_OBJECT (d->decor_window), "realize", + G_CALLBACK (frame_window_realized), (gpointer) d); + + gtk_widget_show_all (d->decor_window); + gtk_widget_show (d->decor_window); + + g_object_set_data (G_OBJECT (d->frame_window), "client_wnck_window", win); + } + else + { + d->frame_window = NULL; + + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + d->event_windows[i][j] = + XCreateWindow (xdisplay, + frame, + 0, 0, 1, 1, 0, + CopyFromParent, CopyFromParent, CopyFromParent, + CWOverrideRedirect | CWEventMask, &attr); + + if (cursor[i][j].cursor) + XDefineCursor (xdisplay, d->event_windows[i][j], + cursor[i][j].cursor); + } + } + + attr.event_mask |= ButtonReleaseMask; + + for (i = 0; i < BUTTON_NUM; i++) + { + d->button_windows[i] = + XCreateWindow (xdisplay, + frame, + 0, 0, 1, 1, 0, + CopyFromParent, CopyFromParent, CopyFromParent, + CWOverrideRedirect | CWEventMask, &attr); + + d->button_states[i] = 0; + } + } + + gdk_display_sync (gdk_display_get_default ()); + if (!gdk_error_trap_pop ()) + { + if (get_mwm_prop (xid) & (MWM_DECOR_ALL | MWM_DECOR_TITLE)) + d->decorated = TRUE; + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + g_hash_table_insert (frame_table, + GINT_TO_POINTER (d->event_windows[i][j]), + GINT_TO_POINTER (xid)); + + for (i = 0; i < BUTTON_NUM; i++) + g_hash_table_insert (frame_table, + GINT_TO_POINTER (d->button_windows[i]), + GINT_TO_POINTER (xid)); + + if (d->frame_window) + { + g_hash_table_insert (frame_table, + GINT_TO_POINTER (frame), + GINT_TO_POINTER (xid)); + } + update_window_decoration_state (win); + update_window_decoration_actions (win); + update_window_decoration_icon (win); + update_window_decoration_size (win); + + update_event_windows (win); + } + else + { + memset (d->event_windows, 0, sizeof (d->event_windows)); + } + + d->created = TRUE; +} + +static gboolean +update_switcher_window (WnckWindow *win, + Window selected) +{ + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + GdkPixmap *pixmap, *buffer_pixmap = NULL; + gint height, width = 0; + WnckWindow *selected_win; + Display *xdisplay; + + xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + + wnck_window_get_client_window_geometry (win, NULL, NULL, &width, NULL); + + decor_get_default_layout (&switcher_context, width, 1, &d->border_layout); + + width = d->border_layout.width; + height = d->border_layout.height; + + d->decorated = FALSE; + d->draw = draw_switcher_decoration; + + if (!d->pixmap && switcher_pixmap) + { + g_object_ref (G_OBJECT (switcher_pixmap)); + + d->pixmap = switcher_pixmap; + } + + if (!d->buffer_pixmap && switcher_buffer_pixmap) + { + g_object_ref (G_OBJECT (switcher_buffer_pixmap)); + d->buffer_pixmap = switcher_buffer_pixmap; + } + + if (!d->width) + d->width = switcher_width; + + if (!d->height) + d->height = switcher_height; + + selected_win = wnck_window_get (selected); + if (selected_win) + { + glong name_length; + PangoLayoutLine *line; + const gchar *name; + + if (d->name) + { + g_free (d->name); + d->name = NULL; + } + + name = wnck_window_get_name (selected_win); + if (name && (name_length = strlen (name))) + { + if (!d->layout) + { + d->layout = pango_layout_new (pango_context); + if (d->layout) + pango_layout_set_wrap (d->layout, PANGO_WRAP_CHAR); + } + + if (d->layout) + { + int tw; + + tw = width - switcher_context.left_space - + switcher_context.right_space - 64; + pango_layout_set_auto_dir (d->layout, FALSE); + pango_layout_set_width (d->layout, tw * PANGO_SCALE); + pango_layout_set_text (d->layout, name, name_length); + + line = pango_layout_get_line (d->layout, 0); + + name_length = line->length; + if (pango_layout_get_line_count (d->layout) > 1) + { + if (name_length < 4) + { + g_object_unref (G_OBJECT (d->layout)); + d->layout = NULL; + } + else + { + d->name = g_strndup (name, name_length); + strcpy (d->name + name_length - 3, "..."); + } + } + else + d->name = g_strndup (name, name_length); + + if (d->layout) + pango_layout_set_text (d->layout, d->name, name_length); + } + } + else if (d->layout) + { + g_object_unref (G_OBJECT (d->layout)); + d->layout = NULL; + } + } + + if (selected != switcher_selected_window) + { + gtk_label_set_text (GTK_LABEL (switcher_label), ""); + if (selected_win && d->name) + gtk_label_set_text (GTK_LABEL (switcher_label), d->name); + switcher_selected_window = selected; + } + + if (width == d->width && height == d->height) + { + if (!d->gc) + d->gc = gdk_gc_new (d->pixmap); + + if (!d->picture) + { + if (gdk_drawable_get_depth (GDK_DRAWABLE (d->buffer_pixmap)) == 32 || + !d->frame_window) + d->picture = XRenderCreatePicture (xdisplay, + GDK_PIXMAP_XID (buffer_pixmap), + xformat32, 0, NULL); + else + d->picture = XRenderCreatePicture (xdisplay, + GDK_PIXMAP_XID (buffer_pixmap), + xformat24, 0, NULL); + } + queue_decor_draw (d); + return FALSE; + } + + pixmap = create_pixmap (width, height, 32); + if (!pixmap) + return FALSE; + + buffer_pixmap = create_pixmap (width, height, 32); + if (!buffer_pixmap) + { + g_object_unref (G_OBJECT (pixmap)); + return FALSE; + } + + if (switcher_pixmap) + g_object_unref (G_OBJECT (switcher_pixmap)); + + if (switcher_buffer_pixmap) + g_object_unref (G_OBJECT (switcher_buffer_pixmap)); + + if (d->pixmap) + g_object_unref (G_OBJECT (d->pixmap)); + + if (d->buffer_pixmap) + g_object_unref (G_OBJECT (d->buffer_pixmap)); + + if (d->gc) + g_object_unref (G_OBJECT (d->gc)); + + if (d->picture) + XRenderFreePicture (xdisplay, d->picture); + + switcher_pixmap = pixmap; + switcher_buffer_pixmap = buffer_pixmap; + + switcher_width = width; + switcher_height = height; + + g_object_ref (G_OBJECT (pixmap)); + g_object_ref (G_OBJECT (buffer_pixmap)); + + d->pixmap = pixmap; + d->buffer_pixmap = buffer_pixmap; + d->gc = gdk_gc_new (pixmap); + + if (gdk_drawable_get_depth (GDK_DRAWABLE (d->buffer_pixmap)) == 32 || + !d->frame_window) + d->picture = XRenderCreatePicture (xdisplay, + GDK_PIXMAP_XID (buffer_pixmap), + xformat32, 0, NULL); + else + d->picture = XRenderCreatePicture (xdisplay, + GDK_PIXMAP_XID (buffer_pixmap), + xformat24, 0, NULL); + + d->width = width; + d->height = height; + + d->prop_xid = wnck_window_get_xid (win); + + queue_decor_draw (d); + + return TRUE; +} + +static void +remove_frame_window (WnckWindow *win) +{ + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + Display *xdisplay; + + xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + + if (d->pixmap) + { + g_object_unref (G_OBJECT (d->pixmap)); + d->pixmap = NULL; + } + + if (d->buffer_pixmap) + { + g_object_unref (G_OBJECT (d->buffer_pixmap)); + d->buffer_pixmap = NULL; + } + + if (d->gc) + { + g_object_unref (G_OBJECT (d->gc)); + d->gc = NULL; + } + + if (d->picture && !d->frame_window) + { + XRenderFreePicture (xdisplay, d->picture); + d->picture = 0; + } + + if (d->name) + { + g_free (d->name); + d->name = NULL; + } + + if (d->layout) + { + g_object_unref (G_OBJECT (d->layout)); + d->layout = NULL; + } + + if (d->icon) + { + cairo_pattern_destroy (d->icon); + d->icon = NULL; + } + + if (d->icon_pixmap) + { + g_object_unref (G_OBJECT (d->icon_pixmap)); + d->icon_pixmap = NULL; + } + + if (d->icon_pixbuf) + { + g_object_unref (G_OBJECT (d->icon_pixbuf)); + d->icon_pixbuf = NULL; + } + + if (d->force_quit_dialog) + { + GtkWidget *dialog = d->force_quit_dialog; + + d->force_quit_dialog = NULL; + gtk_widget_destroy (dialog); + } + + if (d->frame_window) + { + gdk_window_destroy (d->frame_window); + d->frame_window = NULL; + } + + if (d->decor_image) + { + g_object_unref (d->decor_image); + d->decor_image = NULL; + } + + if (d->decor_event_box) + { + g_object_unref (d->decor_event_box); + d->decor_event_box = NULL; + } + + if (d->decor_window) + { + g_object_unref (d->decor_window); + d->decor_window = NULL; + } + + d->width = 0; + d->height = 0; + + d->decorated = FALSE; + + d->state = 0; + d->actions = 0; + + d->context = NULL; + d->shadow = NULL; + + draw_list = g_slist_remove (draw_list, d); +} + +static void +active_window_changed (WnckScreen *screen) +{ + WnckWindow *win; + decor_t *d; + + win = wnck_screen_get_previously_active_window (screen); + if (win) + { + d = g_object_get_data (G_OBJECT (win), "decor"); + if (d && d->pixmap) + { + d->active = wnck_window_is_active (win); + queue_decor_draw (d); + } + } + + win = wnck_screen_get_active_window (screen); + if (win) + { + d = g_object_get_data (G_OBJECT (win), "decor"); + if (d && d->pixmap) + { + d->active = wnck_window_is_active (win); + queue_decor_draw (d); + } + } +} + +static void +window_opened (WnckScreen *screen, + WnckWindow *win) +{ + decor_t *d; + Window window; + gulong xid; + + d = calloc (1, sizeof (decor_t)); + if (!d) + return; + + wnck_window_get_client_window_geometry (win, NULL, NULL, + &d->client_width, + &d->client_height); + + d->draw = theme_draw_window_decoration; + + d->created = FALSE; + d->pixmap = NULL; + d->gc = NULL; + d->buffer_pixmap = NULL; + d->picture = None; + + connect_window (win); + + g_object_set_data (G_OBJECT (win), "decor", d); + + xid = wnck_window_get_xid (win); + + if (get_window_prop (xid, select_window_atom, &window)) + { + d->prop_xid = wnck_window_get_xid (win); + update_switcher_window (win, window); + } + else if (get_window_prop (xid, frame_input_window_atom, &window)) + { + add_frame_window (win, window, FALSE); + } + else if (get_window_prop (xid, frame_output_window_atom, &window)) + { + add_frame_window (win, window, TRUE); + } +} + +static void +window_closed (WnckScreen *screen, + WnckWindow *win) +{ + Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + + remove_frame_window (win); + + g_object_set_data (G_OBJECT (win), "decor", NULL); + + gdk_error_trap_push (); + XDeleteProperty (xdisplay, wnck_window_get_xid (win), win_decor_atom); + gdk_display_sync (gdk_display_get_default ()); + gdk_error_trap_pop (); + + g_free (d); +} + +static void +connect_screen (WnckScreen *screen) +{ + GList *windows; + + g_signal_connect_object (G_OBJECT (screen), "active_window_changed", + G_CALLBACK (active_window_changed), + 0, 0); + g_signal_connect_object (G_OBJECT (screen), "window_opened", + G_CALLBACK (window_opened), + 0, 0); + g_signal_connect_object (G_OBJECT (screen), "window_closed", + G_CALLBACK (window_closed), + 0, 0); + + windows = wnck_screen_get_windows (screen); + while (windows != NULL) + { + window_opened (screen, windows->data); + windows = windows->next; + } +} + + + +static void force_quit_dialog_realize (GtkWidget *dialog, void *data) { @@ -5157,7 +6175,7 @@ event_filter_func (GdkXEvent *gdkxevent, GINT_TO_POINTER (xevent->xmotion.window)); break; case PropertyNotify: - if (xevent->xproperty.atom == frame_window_atom) + if (xevent->xproperty.atom == frame_input_window_atom) { WnckWindow *win; @@ -5170,8 +6188,28 @@ event_filter_func (GdkXEvent *gdkxevent, if (!get_window_prop (xid, select_window_atom, &window)) { - if (get_window_prop (xid, frame_window_atom, &frame)) - add_frame_window (win, frame); + if (get_window_prop (xid, frame_input_window_atom, &frame)) + add_frame_window (win, frame, FALSE); + else + remove_frame_window (win); + } + } + } + if (xevent->xproperty.atom == frame_output_window_atom) + { + WnckWindow *win; + + xid = xevent->xproperty.window; + + win = wnck_window_get (xid); + if (win) + { + Window frame, window; + + if (!get_window_prop (xid, select_window_atom, &window)) + { + if (get_window_prop (xid, frame_output_window_atom, &frame)) + add_frame_window (win, frame, TRUE); else remove_frame_window (win); } @@ -5299,15 +6337,59 @@ event_filter_func (GdkXEvent *gdkxevent, if (d->decorated) { gint i, j; + decor_event gtkwd_event; + decor_event_type gtkwd_type; + + gtkwd_event.window = xevent->xany.window; + + switch (xevent->type) + { + case ButtonPress: + gtkwd_type = GButtonPress; + gtkwd_event.button = xevent->xbutton.button; + gtkwd_event.x = xevent->xbutton.x; + gtkwd_event.y = xevent->xbutton.y; + gtkwd_event.x_root = xevent->xbutton.x_root; + gtkwd_event.y_root = xevent->xbutton.y_root; + gtkwd_event.time = xevent->xbutton.time; + break; + case ButtonRelease: + gtkwd_type = GButtonRelease; + gtkwd_event.button = xevent->xbutton.button; + gtkwd_event.x = xevent->xbutton.x; + gtkwd_event.y = xevent->xbutton.y; + gtkwd_event.x_root = xevent->xbutton.x_root; + gtkwd_event.y_root = xevent->xbutton.y_root; + gtkwd_event.time = xevent->xbutton.time; + break; + case EnterNotify: + gtkwd_type = GEnterNotify; + gtkwd_event.x = xevent->xcrossing.x; + gtkwd_event.y = xevent->xcrossing.y; + gtkwd_event.x_root = xevent->xcrossing.x_root; + gtkwd_event.y_root = xevent->xcrossing.y_root; + gtkwd_event.time = xevent->xcrossing.time; + break; + case LeaveNotify: + gtkwd_type = GLeaveNotify; + gtkwd_event.x = xevent->xcrossing.x; + gtkwd_event.y = xevent->xcrossing.y; + gtkwd_event.x_root = xevent->xcrossing.x_root; + gtkwd_event.y_root = xevent->xcrossing.y_root; + gtkwd_event.time = xevent->xcrossing.time; + break; + default: + break; + } for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) if (d->event_windows[i][j] == xevent->xany.window) - (*callback[i][j]) (win, xevent); + (*callback[i][j]) (win, >kwd_event, gtkwd_type); for (i = 0; i < BUTTON_NUM; i++) if (d->button_windows[i] == xevent->xany.window) - (*button_callback[i]) (win, xevent); + (*button_callback[i]) (win, >kwd_event, gtkwd_type); } } } @@ -5589,7 +6671,10 @@ draw_border_shape (Display *xdisplay, decor_get_default_layout (c, 1, 1, &d.border_layout); screen = gdk_display_get_default_screen (gdk_display_get_default ()); - colormap = gdk_screen_get_rgba_colormap (screen); + if (gdk_drawable_get_depth (GDK_DRAWABLE (d.pixmap)) == 32) + colormap = gdk_screen_get_rgba_colormap (screen); + else + colormap = gdk_screen_get_rgb_colormap (screen); gdk_drawable_set_colormap (d.pixmap, colormap); @@ -6818,34 +7903,63 @@ init_settings (WnckScreen *screen) } #endif - style_window = gtk_window_new (GTK_WINDOW_POPUP); + sytle_window_rgba = gtk_window_new (GTK_WINDOW_POPUP); gdkscreen = gdk_display_get_default_screen (gdk_display_get_default ()); colormap = gdk_screen_get_rgba_colormap (gdkscreen); if (colormap) - gtk_widget_set_colormap (style_window, colormap); + gtk_widget_set_colormap (sytle_window_rgba, colormap); + + gtk_widget_realize (sytle_window_rgba); + + switcher_label = gtk_label_new (""); + switcher_label_obj = gtk_widget_get_accessible (switcher_label); + atk_object_set_role (switcher_label_obj, ATK_ROLE_STATUSBAR); + gtk_container_add (GTK_CONTAINER (sytle_window_rgba), switcher_label); + + gtk_widget_set_size_request (sytle_window_rgba, 0, 0); + gtk_window_move (GTK_WINDOW (sytle_window_rgba), -100, -100); + gtk_widget_show_all (sytle_window_rgba); + + g_signal_connect_object (sytle_window_rgba, "style-set", + G_CALLBACK (style_changed), + 0, 0); + + settings = gtk_widget_get_settings (sytle_window_rgba); + + g_object_get (G_OBJECT (settings), "gtk-double-click-time", + &double_click_timeout, NULL); + + pango_context = gtk_widget_create_pango_context (sytle_window_rgba); + + sytle_window_rgb = gtk_window_new (GTK_WINDOW_POPUP); + + gdkscreen = gdk_display_get_default_screen (gdk_display_get_default ()); + colormap = gdk_screen_get_rgb_colormap (gdkscreen); + if (colormap) + gtk_widget_set_colormap (sytle_window_rgb, colormap); - gtk_widget_realize (style_window); + gtk_widget_realize (sytle_window_rgb); switcher_label = gtk_label_new (""); switcher_label_obj = gtk_widget_get_accessible (switcher_label); atk_object_set_role (switcher_label_obj, ATK_ROLE_STATUSBAR); - gtk_container_add (GTK_CONTAINER (style_window), switcher_label); + gtk_container_add (GTK_CONTAINER (sytle_window_rgb), switcher_label); - gtk_widget_set_size_request (style_window, 0, 0); - gtk_window_move (GTK_WINDOW (style_window), -100, -100); - gtk_widget_show_all (style_window); + gtk_widget_set_size_request (sytle_window_rgb, 0, 0); + gtk_window_move (GTK_WINDOW (sytle_window_rgb), -100, -100); + gtk_widget_show_all (sytle_window_rgb); - g_signal_connect_object (style_window, "style-set", + g_signal_connect_object (sytle_window_rgb, "style-set", G_CALLBACK (style_changed), 0, 0); - settings = gtk_widget_get_settings (style_window); + settings = gtk_widget_get_settings (sytle_window_rgb); g_object_get (G_OBJECT (settings), "gtk-double-click-time", &double_click_timeout, NULL); - pango_context = gtk_widget_create_pango_context (style_window); + pango_context = gtk_widget_create_pango_context (sytle_window_rgb); #ifdef USE_GCONF use_system_font = gconf_client_get_bool (gconf, @@ -6856,8 +7970,8 @@ init_settings (WnckScreen *screen) button_layout_changed (gconf); #endif - update_style (style_window); - + update_style (sytle_window_rgba); + update_style (sytle_window_rgb); #ifdef USE_GCONF titlebar_font_changed (gconf); #endif @@ -7011,7 +8125,8 @@ main (int argc, char *argv[]) xdisplay = gdk_x11_display_get_xdisplay (gdkdisplay); gdkscreen = gdk_display_get_default_screen (gdkdisplay); - frame_window_atom = XInternAtom (xdisplay, DECOR_INPUT_FRAME_ATOM_NAME, FALSE); + frame_input_window_atom = XInternAtom (xdisplay, DECOR_INPUT_FRAME_ATOM_NAME, FALSE); + frame_output_window_atom = XInternAtom (xdisplay, DECOR_OUTPUT_FRAME_ATOM_NAME, FALSE); win_decor_atom = XInternAtom (xdisplay, DECOR_WINDOW_ATOM_NAME, FALSE); win_blur_decor_atom = XInternAtom (xdisplay, DECOR_BLUR_ATOM_NAME, FALSE); wm_move_resize_atom = XInternAtom (xdisplay, "_NET_WM_MOVERESIZE", FALSE); @@ -7068,7 +8183,8 @@ main (int argc, char *argv[]) } } - xformat = XRenderFindStandardFormat (xdisplay, PictStandardARGB32); + xformat32 = XRenderFindStandardFormat (xdisplay, PictStandardARGB32); + xformat24 = XRenderFindStandardFormat (xdisplay, PictStandardRGB24); frame_table = g_hash_table_new (NULL, NULL); @@ -7101,7 +8217,8 @@ main (int argc, char *argv[]) } decor_set_dm_check_hint (xdisplay, gdk_screen_get_number (gdkscreen), - WINDOW_DECORATION_TYPE_PIXMAP); + WINDOW_DECORATION_TYPE_PIXMAP | + WINDOW_DECORATION_TYPE_WINDOW); update_default_decorations (gdkscreen); diff --git a/plugins/imgpng/src/imgpng.cpp b/plugins/imgpng/src/imgpng.cpp index 3b95acf..05f540b 100644 --- a/plugins/imgpng/src/imgpng.cpp +++ b/plugins/imgpng/src/imgpng.cpp @@ -92,7 +92,7 @@ PngScreen::readPngData (png_struct *png, /* expand gray bit depth if needed */ if (colorType == PNG_COLOR_TYPE_GRAY && depth < 8) - png_set_gray_1_2_4_to_8 (png); + png_set_expand_gray_1_2_4_to_8 (png); /* transform transparency to alpha */ if (png_get_valid (png, info, PNG_INFO_tRNS)) @@ -169,7 +169,7 @@ PngScreen::readPng (std::ifstream &file, file.read ((char *) png_sig, PNG_SIG_SIZE); if (file.fail ()) return false; - if (png_check_sig (png_sig, PNG_SIG_SIZE) == 0) + if (png_sig_cmp (png_sig, 0, PNG_SIG_SIZE) == 0) return false; png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); diff --git a/plugins/place/src/place.cpp b/plugins/place/src/place.cpp index f276161..fe48599 100644 --- a/plugins/place/src/place.cpp +++ b/plugins/place/src/place.cpp @@ -590,6 +590,12 @@ PlaceWindow::doValidateResizeRequest (unsigned int &mask, top += window->input ().top; bottom -= window->input ().bottom + 2 * window->serverGeometry ().border (); + /* always validate position if the application changed only its size, + as it might become partially offscreen because of that */ + + if (!(mask & (CWX | CWY)) && (mask & (CWWidth | CWHeight))) + sizeOnly = FALSE; + if ((right - left) != xwc->width) { xwc->width = right - left; @@ -1358,10 +1364,6 @@ PlaceWindow::getStrategy () return NoPlacement; } - /* no placement for unmovable windows */ - if (!(window->actions () & CompWindowActionMoveMask)) - return NoPlacement; - if (!ps->optionGetForcePlacementMatch ().evaluate (window)) { if ((window->type () & CompWindowTypeNormalMask) || diff --git a/src/window.cpp b/src/window.cpp index 92b948f..eb5243f 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1416,8 +1416,19 @@ CompWindow::resize (CompWindow::Geometry gm) priv->attrib.width, priv->attrib.height, priv->attrib.border_width); - priv->width = pw; - priv->height = ph; + if (!priv->mapNum && priv->unmapRefCnt > 0 && + priv->attrib.map_state == IsViewable) + { + /* keep old pixmap for windows that are unmapped on the client side, + * but not yet on our side as it's pretty likely that plugins are + * currently using it for animations + */ + } + else + { + priv->width = pw; + priv->height = ph; + } if (priv->mapNum) priv->updateRegion (); |