File: | ui/frames.c |
Warning: | line 1696, column 16 This statement is never executed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ |
2 | |
3 | /* Croma window frame manager widget */ |
4 | |
5 | /* |
6 | * Copyright (C) 2001 Havoc Pennington |
7 | * Copyright (C) 2003 Red Hat, Inc. |
8 | * Copyright (C) 2005, 2006 Elijah Newren |
9 | * |
10 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License as |
12 | * published by the Free Software Foundation; either version 2 of the |
13 | * License, or (at your option) any later version. |
14 | * |
15 | * This program is distributed in the hope that it will be useful, but |
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 | * General Public License for more details. |
19 | * |
20 | * You should have received a copy of the GNU General Public License |
21 | * along with this program; if not, write to the Free Software |
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA |
23 | * 02110-1301, USA. |
24 | */ |
25 | |
26 | #include <config.h> |
27 | #include <math.h> |
28 | #include <string.h> |
29 | #include "boxes.h" |
30 | #include "frames.h" |
31 | #include "util.h" |
32 | #include "core.h" |
33 | #include "menu.h" |
34 | #include "fixedtip.h" |
35 | #include "theme.h" |
36 | #include "prefs.h" |
37 | #include "ui.h" |
38 | |
39 | #ifdef HAVE_SHAPE |
40 | #include <X11/extensions/shape.h> |
41 | #endif |
42 | |
43 | #include <cairo-xlib.h> |
44 | |
45 | G_DEFINE_TYPE (MetaFrames, meta_frames, CTK_TYPE_WINDOW)static void meta_frames_init (MetaFrames *self); static void meta_frames_class_init (MetaFramesClass *klass); static GType meta_frames_get_type_once (void); static gpointer meta_frames_parent_class = ((void*)0 ); static gint MetaFrames_private_offset; static void meta_frames_class_intern_init (gpointer klass) { meta_frames_parent_class = g_type_class_peek_parent (klass); if (MetaFrames_private_offset != 0) g_type_class_adjust_private_offset (klass, &MetaFrames_private_offset); meta_frames_class_init ((MetaFramesClass*) klass); } __attribute__ ((__unused__)) static inline gpointer meta_frames_get_instance_private (MetaFrames *self) { return (((gpointer) ((guint8*) (self) + (glong) (MetaFrames_private_offset )))); } GType meta_frames_get_type (void) { static gsize static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); (void ) (0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0 )); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id )); }))) { GType g_define_type_id = meta_frames_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id) = (g_define_type_id) ) : (void) 0; g_once_init_leave ((&static_g_define_type_id ), (gsize) (g_define_type_id)); })); } return static_g_define_type_id ; } __attribute__ ((__noinline__)) static GType meta_frames_get_type_once (void) { GType g_define_type_id = g_type_register_static_simple ((ctk_window_get_type ()), g_intern_static_string ("MetaFrames" ), sizeof (MetaFramesClass), (GClassInitFunc)(void (*)(void)) meta_frames_class_intern_init, sizeof (MetaFrames), (GInstanceInitFunc )(void (*)(void)) meta_frames_init, (GTypeFlags) 0); { {{};} } return g_define_type_id; }; |
46 | |
47 | #define DEFAULT_INNER_BUTTON_BORDER3 3 |
48 | |
49 | static void meta_frames_class_init (MetaFramesClass *klass); |
50 | static void meta_frames_init (MetaFrames *frames); |
51 | static void meta_frames_destroy (CtkWidget *object); |
52 | static void meta_frames_finalize (GObject *object); |
53 | static void meta_frames_style_updated (CtkWidget *widget); |
54 | |
55 | static void meta_frames_update_prelit_control (MetaFrames *frames, |
56 | MetaUIFrame *frame, |
57 | MetaFrameControl control); |
58 | static gboolean meta_frames_button_press_event (CtkWidget *widget, |
59 | CdkEventButton *event); |
60 | static gboolean meta_frames_button_release_event (CtkWidget *widget, |
61 | CdkEventButton *event); |
62 | static gboolean meta_frames_motion_notify_event (CtkWidget *widget, |
63 | CdkEventMotion *event); |
64 | static gboolean meta_frames_destroy_event (CtkWidget *widget, |
65 | CdkEventAny *event); |
66 | static gboolean meta_frames_draw (CtkWidget *widget, |
67 | cairo_t *cr); |
68 | static gboolean meta_frames_enter_notify_event (CtkWidget *widget, |
69 | CdkEventCrossing *event); |
70 | static gboolean meta_frames_leave_notify_event (CtkWidget *widget, |
71 | CdkEventCrossing *event); |
72 | |
73 | static void meta_frames_attach_style (MetaFrames *frames, |
74 | MetaUIFrame *frame); |
75 | |
76 | static void meta_frames_paint_to_drawable (MetaFrames *frames, |
77 | MetaUIFrame *frame, |
78 | cairo_t *cr); |
79 | |
80 | static void meta_frames_calc_geometry (MetaFrames *frames, |
81 | MetaUIFrame *frame, |
82 | MetaFrameGeometry *fgeom); |
83 | |
84 | static void meta_frames_ensure_layout (MetaFrames *frames, |
85 | MetaUIFrame *frame); |
86 | |
87 | static MetaUIFrame* meta_frames_lookup_window (MetaFrames *frames, |
88 | Window xwindow); |
89 | |
90 | static void meta_frames_font_changed (MetaFrames *frames); |
91 | static void meta_frames_button_layout_changed (MetaFrames *frames); |
92 | |
93 | |
94 | static CdkRectangle* control_rect (MetaFrameControl control, |
95 | MetaFrameGeometry *fgeom); |
96 | static MetaFrameControl get_control (MetaFrames *frames, |
97 | MetaUIFrame *frame, |
98 | int x, |
99 | int y); |
100 | static void clear_tip (MetaFrames *frames); |
101 | static void invalidate_all_caches (MetaFrames *frames); |
102 | static void invalidate_whole_window (MetaFrames *frames, |
103 | MetaUIFrame *frame); |
104 | |
105 | static GObject * |
106 | meta_frames_constructor (GType gtype, |
107 | guint n_properties, |
108 | GObjectConstructParam *properties) |
109 | { |
110 | GObject *object; |
111 | GObjectClass *gobject_class; |
112 | |
113 | gobject_class = G_OBJECT_CLASS (meta_frames_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((meta_frames_parent_class)), (((GType) ((20) << (2) ))))))); |
114 | object = gobject_class->constructor (gtype, n_properties, properties); |
115 | |
116 | return object; |
117 | } |
118 | |
119 | static void |
120 | meta_frames_class_init (MetaFramesClass *class) |
121 | { |
122 | GObjectClass *gobject_class; |
123 | CtkWidgetClass *widget_class; |
124 | |
125 | gobject_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((class)), (((GType) ((20) << (2)))))))); |
126 | widget_class = (CtkWidgetClass*) class; |
127 | |
128 | gobject_class->constructor = meta_frames_constructor; |
129 | gobject_class->finalize = meta_frames_finalize; |
130 | widget_class->destroy = meta_frames_destroy; |
131 | widget_class->style_updated = meta_frames_style_updated; |
132 | |
133 | widget_class->draw = meta_frames_draw; |
134 | widget_class->destroy_event = meta_frames_destroy_event; |
135 | widget_class->button_press_event = meta_frames_button_press_event; |
136 | widget_class->button_release_event = meta_frames_button_release_event; |
137 | widget_class->motion_notify_event = meta_frames_motion_notify_event; |
138 | widget_class->enter_notify_event = meta_frames_enter_notify_event; |
139 | widget_class->leave_notify_event = meta_frames_leave_notify_event; |
140 | } |
141 | |
142 | static gint |
143 | unsigned_long_equal (gconstpointer v1, |
144 | gconstpointer v2) |
145 | { |
146 | return *((const gulong*) v1) == *((const gulong*) v2); |
147 | } |
148 | |
149 | static guint |
150 | unsigned_long_hash (gconstpointer v) |
151 | { |
152 | gulong val = * (const gulong *) v; |
153 | |
154 | /* I'm not sure this works so well. */ |
155 | #if GLIB_SIZEOF_LONG8 > 4 |
156 | return (guint) (val ^ (val >> 32)); |
157 | #else |
158 | return val; |
159 | #endif |
160 | } |
161 | |
162 | static void |
163 | prefs_changed_callback (MetaPreference pref, |
164 | void *data) |
165 | { |
166 | switch (pref) |
167 | { |
168 | case META_PREF_TITLEBAR_FONT: |
169 | meta_frames_font_changed (META_FRAMES (data)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((meta_frames_get_type ()))))))); |
170 | break; |
171 | case META_PREF_BUTTON_LAYOUT: |
172 | meta_frames_button_layout_changed (META_FRAMES (data)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((meta_frames_get_type ()))))))); |
173 | break; |
174 | default: |
175 | break; |
176 | } |
177 | } |
178 | |
179 | static CtkStyleContext * |
180 | create_style_context (MetaFrames *frames, |
181 | const gchar *variant) |
182 | { |
183 | CtkStyleContext *style; |
184 | CdkScreen *screen; |
185 | char *theme_name; |
186 | |
187 | screen = ctk_widget_get_screen (CTK_WIDGET (frames)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((frames)), ((ctk_widget_get_type ()))))))); |
188 | g_object_get (ctk_settings_get_for_screen (screen), |
189 | "ctk-theme-name", &theme_name, |
190 | NULL((void*)0)); |
191 | |
192 | style = ctk_style_context_new (); |
193 | ctk_style_context_set_path (style, |
194 | ctk_widget_get_path (CTK_WIDGET (frames)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((frames)), ((ctk_widget_get_type ())))))))); |
195 | |
196 | if (theme_name && *theme_name) |
197 | { |
198 | CtkCssProvider *provider; |
199 | |
200 | provider = ctk_css_provider_get_named (theme_name, variant); |
201 | ctk_style_context_add_provider (style, |
202 | CTK_STYLE_PROVIDER (provider)((((CtkStyleProvider*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((provider)), ((ctk_style_provider_get_type ( ))))))), |
203 | CTK_STYLE_PROVIDER_PRIORITY_SETTINGS400); |
204 | } |
205 | |
206 | if (theme_name) |
207 | g_free (theme_name); |
208 | |
209 | return style; |
210 | } |
211 | |
212 | static CtkStyleContext * |
213 | meta_frames_get_theme_variant (MetaFrames *frames, |
214 | const gchar *variant) |
215 | { |
216 | CtkStyleContext *style; |
217 | |
218 | style = g_hash_table_lookup (frames->style_variants, variant); |
219 | if (style == NULL((void*)0)) |
220 | { |
221 | style = create_style_context (frames, variant); |
222 | g_hash_table_insert (frames->style_variants, g_strdup (variant), style); |
223 | } |
224 | |
225 | return style; |
226 | } |
227 | |
228 | static void |
229 | update_style_contexts (MetaFrames *frames) |
230 | { |
231 | GList *variant_list, *variant; |
232 | |
233 | if (frames->normal_style) |
234 | g_object_unref (frames->normal_style); |
235 | frames->normal_style = create_style_context (frames, NULL((void*)0)); |
236 | |
237 | variant_list = g_hash_table_get_keys (frames->style_variants); |
238 | for (variant = variant_list; variant; variant = variant->next) |
239 | { |
240 | CtkStyleContext *style; |
241 | |
242 | style = create_style_context (frames, (char *)variant->data); |
243 | g_hash_table_insert (frames->style_variants, |
244 | g_strdup (variant->data), style); |
245 | } |
246 | g_list_free (variant_list); |
247 | } |
248 | static void |
249 | meta_frames_init (MetaFrames *frames) |
250 | { |
251 | frames->text_heights = g_hash_table_new (NULL((void*)0), NULL((void*)0)); |
252 | |
253 | frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal); |
254 | |
255 | frames->tooltip_timeout = 0; |
256 | |
257 | frames->expose_delay_count = 0; |
258 | |
259 | frames->invalidate_cache_timeout_id = 0; |
260 | frames->invalidate_frames = NULL((void*)0); |
261 | frames->cache = g_hash_table_new (g_direct_hash, g_direct_equal); |
262 | frames->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal, |
263 | g_free, g_object_unref); |
264 | update_style_contexts (frames); |
265 | |
266 | meta_prefs_add_listener (prefs_changed_callback, frames); |
267 | } |
268 | |
269 | static void |
270 | listify_func (gpointer key, gpointer value, gpointer data) |
271 | { |
272 | GSList **listp; |
273 | |
274 | listp = data; |
275 | *listp = g_slist_prepend (*listp, value); |
276 | } |
277 | |
278 | static void |
279 | meta_frames_destroy (CtkWidget *widget) |
280 | { |
281 | GSList *winlist; |
282 | GSList *tmp; |
283 | MetaFrames *frames; |
284 | |
285 | frames = META_FRAMES (widget)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((meta_frames_get_type ())))))); |
286 | |
287 | clear_tip (frames); |
288 | |
289 | winlist = NULL((void*)0); |
290 | g_hash_table_foreach (frames->frames, listify_func, &winlist); |
291 | |
292 | /* Unmanage all frames */ |
293 | for (tmp = winlist; tmp != NULL((void*)0); tmp = tmp->next) |
294 | { |
295 | MetaUIFrame *frame; |
296 | |
297 | frame = tmp->data; |
298 | |
299 | meta_frames_unmanage_window (frames, frame->xwindow); |
300 | } |
301 | g_slist_free (winlist); |
302 | |
303 | if (frames->normal_style) |
304 | { |
305 | g_object_unref (frames->normal_style); |
306 | frames->normal_style = NULL((void*)0); |
307 | } |
308 | |
309 | if (frames->style_variants) |
310 | { |
311 | g_hash_table_destroy (frames->style_variants); |
312 | frames->style_variants = NULL((void*)0); |
313 | } |
314 | |
315 | CTK_WIDGET_CLASS (meta_frames_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((meta_frames_parent_class)), ((ctk_widget_get_type ())))) ))->destroy (widget); |
316 | } |
317 | |
318 | static void |
319 | meta_frames_finalize (GObject *object) |
320 | { |
321 | MetaFrames *frames; |
322 | |
323 | frames = META_FRAMES (object)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((meta_frames_get_type ())))))); |
324 | |
325 | meta_prefs_remove_listener (prefs_changed_callback, frames); |
326 | |
327 | g_hash_table_destroy (frames->text_heights); |
328 | |
329 | invalidate_all_caches (frames); |
330 | if (frames->invalidate_cache_timeout_id) |
331 | g_source_remove (frames->invalidate_cache_timeout_id); |
332 | |
333 | g_assert (g_hash_table_size (frames->frames) == 0)do { if (g_hash_table_size (frames->frames) == 0) ; else g_assertion_message_expr ("croma", "ui/frames.c", 333, ((const char*) (__func__)), "g_hash_table_size (frames->frames) == 0" ); } while (0); |
334 | g_hash_table_destroy (frames->frames); |
335 | g_hash_table_destroy (frames->cache); |
336 | |
337 | G_OBJECT_CLASS (meta_frames_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((meta_frames_parent_class)), (((GType) ((20) << (2) )))))))->finalize (object); |
338 | } |
339 | |
340 | typedef struct |
341 | { |
342 | cairo_rectangle_int_t rect; |
343 | cairo_surface_t *pixmap; |
344 | } CachedFramePiece; |
345 | |
346 | typedef struct |
347 | { |
348 | /* Caches of the four rendered sides in a MetaFrame. |
349 | * Order: top (titlebar), left, right, bottom. |
350 | */ |
351 | CachedFramePiece piece[4]; |
352 | } CachedPixels; |
353 | |
354 | static CachedPixels * |
355 | get_cache (MetaFrames *frames, |
356 | MetaUIFrame *frame) |
357 | { |
358 | CachedPixels *pixels; |
359 | |
360 | pixels = g_hash_table_lookup (frames->cache, frame); |
361 | |
362 | if (!pixels) |
363 | { |
364 | pixels = g_new0 (CachedPixels, 1)((CachedPixels *) g_malloc0_n ((1), sizeof (CachedPixels))); |
365 | g_hash_table_insert (frames->cache, frame, pixels); |
366 | } |
367 | |
368 | return pixels; |
369 | } |
370 | |
371 | static void |
372 | invalidate_cache (MetaFrames *frames, |
373 | MetaUIFrame *frame) |
374 | { |
375 | CachedPixels *pixels = get_cache (frames, frame); |
376 | int i; |
377 | |
378 | for (i = 0; i < 4; i++) |
379 | if (pixels->piece[i].pixmap) |
380 | cairo_surface_destroy (pixels->piece[i].pixmap); |
381 | |
382 | g_free (pixels); |
383 | g_hash_table_remove (frames->cache, frame); |
384 | } |
385 | |
386 | static void |
387 | invalidate_all_caches (MetaFrames *frames) |
388 | { |
389 | GList *l; |
390 | |
391 | for (l = frames->invalidate_frames; l; l = l->next) |
392 | { |
393 | MetaUIFrame *frame = l->data; |
394 | |
395 | invalidate_cache (frames, frame); |
396 | } |
397 | |
398 | g_list_free (frames->invalidate_frames); |
399 | frames->invalidate_frames = NULL((void*)0); |
400 | } |
401 | |
402 | static gboolean |
403 | invalidate_cache_timeout (gpointer data) |
404 | { |
405 | MetaFrames *frames = data; |
406 | |
407 | invalidate_all_caches (frames); |
408 | frames->invalidate_cache_timeout_id = 0; |
409 | return FALSE(0); |
410 | } |
411 | |
412 | static void |
413 | queue_recalc_func (gpointer key, gpointer value, gpointer data) |
414 | { |
415 | MetaUIFrame *frame; |
416 | MetaFrames *frames; |
417 | |
418 | frames = META_FRAMES (data)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((meta_frames_get_type ())))))); |
419 | frame = value; |
420 | |
421 | invalidate_whole_window (frames, frame); |
422 | meta_core_queue_frame_resize (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
423 | frame->xwindow); |
424 | if (frame->text_layout) |
425 | { |
426 | /* save title to recreate layout */ |
427 | g_free (frame->title); |
428 | |
429 | frame->title = g_strdup (pango_layout_get_text (frame->text_layout)); |
430 | |
431 | g_clear_object (&frame->text_layout)do { _Static_assert (sizeof *((&frame->text_layout)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&frame->text_layout))) _pp = ((&frame->text_layout )); __typeof__ (*((&frame->text_layout))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while (0); |
432 | } |
433 | } |
434 | |
435 | static void |
436 | meta_frames_font_changed (MetaFrames *frames) |
437 | { |
438 | if (g_hash_table_size (frames->text_heights) > 0) |
439 | { |
440 | g_hash_table_destroy (frames->text_heights); |
441 | frames->text_heights = g_hash_table_new (NULL((void*)0), NULL((void*)0)); |
442 | } |
443 | |
444 | /* Queue a draw/resize on all frames */ |
445 | g_hash_table_foreach (frames->frames, |
446 | queue_recalc_func, frames); |
447 | |
448 | } |
449 | |
450 | static void |
451 | queue_draw_func (gpointer key, gpointer value, gpointer data) |
452 | { |
453 | MetaUIFrame *frame; |
454 | MetaFrames *frames; |
455 | |
456 | frames = META_FRAMES (data)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((meta_frames_get_type ())))))); |
457 | frame = value; |
458 | |
459 | invalidate_whole_window (frames, frame); |
460 | } |
461 | |
462 | static void |
463 | meta_frames_button_layout_changed (MetaFrames *frames) |
464 | { |
465 | g_hash_table_foreach (frames->frames, |
466 | queue_draw_func, frames); |
467 | } |
468 | |
469 | static void |
470 | reattach_style_func (gpointer key, gpointer value, gpointer data) |
471 | { |
472 | MetaUIFrame *frame; |
473 | MetaFrames *frames; |
474 | |
475 | frames = META_FRAMES (data)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((meta_frames_get_type ())))))); |
476 | frame = value; |
477 | |
478 | meta_frames_attach_style (frames, frame); |
479 | } |
480 | |
481 | static void |
482 | meta_frames_style_updated (CtkWidget *widget) |
483 | { |
484 | MetaFrames *frames; |
485 | |
486 | frames = META_FRAMES (widget)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((meta_frames_get_type ())))))); |
487 | |
488 | meta_frames_font_changed (frames); |
489 | |
490 | update_style_contexts (frames); |
491 | g_hash_table_foreach (frames->frames, |
492 | reattach_style_func, frames); |
493 | |
494 | CTK_WIDGET_CLASS (meta_frames_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((meta_frames_parent_class)), ((ctk_widget_get_type ())))) ))->style_updated (widget); |
495 | } |
496 | |
497 | static void |
498 | meta_frames_ensure_layout (MetaFrames *frames, |
499 | MetaUIFrame *frame) |
500 | { |
501 | CtkWidget *widget; |
502 | MetaFrameFlags flags; |
503 | MetaFrameType type; |
504 | MetaFrameStyle *style; |
505 | |
506 | g_return_if_fail (ctk_widget_get_realized (CTK_WIDGET (frames)))do { if ((ctk_widget_get_realized (((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((frames)), ((ctk_widget_get_type ())))))) ))) { } else { g_return_if_fail_warning ("croma", ((const char *) (__func__)), "ctk_widget_get_realized (CTK_WIDGET (frames))" ); return; } } while (0); |
507 | |
508 | widget = CTK_WIDGET (frames)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((frames)), ((ctk_widget_get_type ())))))); |
509 | |
510 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
511 | META_CORE_GET_FRAME_FLAGS, &flags, |
512 | META_CORE_GET_FRAME_TYPE, &type, |
513 | META_CORE_GET_END); |
514 | |
515 | style = meta_theme_get_frame_style (meta_theme_get_current (), |
516 | type, flags); |
517 | |
518 | if (style != frame->cache_style) |
519 | { |
520 | if (frame->text_layout) |
521 | { |
522 | /* save title to recreate layout */ |
523 | g_free (frame->title); |
524 | |
525 | frame->title = g_strdup (pango_layout_get_text (frame->text_layout)); |
526 | |
527 | g_clear_object (&frame->text_layout)do { _Static_assert (sizeof *((&frame->text_layout)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&frame->text_layout))) _pp = ((&frame->text_layout )); __typeof__ (*((&frame->text_layout))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while (0); |
528 | } |
529 | } |
530 | |
531 | frame->cache_style = style; |
532 | |
533 | if (frame->text_layout == NULL((void*)0)) |
534 | { |
535 | gpointer key, value; |
536 | PangoFontDescription *font_desc; |
537 | double scale; |
538 | int size; |
539 | |
540 | scale = meta_theme_get_title_scale (meta_theme_get_current (), |
541 | type, |
542 | flags); |
543 | |
544 | frame->text_layout = ctk_widget_create_pango_layout (widget, frame->title); |
545 | |
546 | pango_layout_set_ellipsize (frame->text_layout, PANGO_ELLIPSIZE_END); |
547 | pango_layout_set_auto_dir (frame->text_layout, FALSE(0)); |
548 | |
549 | pango_layout_set_single_paragraph_mode (frame->text_layout, TRUE(!(0))); |
550 | |
551 | font_desc = meta_ctk_widget_get_font_desc (widget, scale, |
552 | meta_prefs_get_titlebar_font ()); |
553 | |
554 | size = pango_font_description_get_size (font_desc); |
555 | |
556 | if (g_hash_table_lookup_extended (frames->text_heights, |
557 | GINT_TO_POINTER (size)((gpointer) (glong) (size)), |
558 | &key, &value)) |
559 | { |
560 | frame->text_height = GPOINTER_TO_INT (value)((gint) (glong) (value)); |
561 | } |
562 | else |
563 | { |
564 | frame->text_height = |
565 | meta_pango_font_desc_get_text_height (font_desc, |
566 | ctk_widget_get_pango_context (widget)); |
567 | |
568 | g_hash_table_replace (frames->text_heights, |
569 | GINT_TO_POINTER (size)((gpointer) (glong) (size)), |
570 | GINT_TO_POINTER (frame->text_height)((gpointer) (glong) (frame->text_height))); |
571 | } |
572 | |
573 | pango_layout_set_font_description (frame->text_layout, |
574 | font_desc); |
575 | |
576 | pango_font_description_free (font_desc); |
577 | |
578 | /* Save some RAM */ |
579 | g_free (frame->title); |
580 | frame->title = NULL((void*)0); |
581 | } |
582 | } |
583 | |
584 | static void |
585 | meta_frames_calc_geometry (MetaFrames *frames, |
586 | MetaUIFrame *frame, |
587 | MetaFrameGeometry *fgeom) |
588 | { |
589 | int width, height, scale; |
590 | MetaFrameFlags flags; |
591 | MetaFrameType type; |
592 | MetaButtonLayout button_layout; |
593 | |
594 | scale = cdk_window_get_scale_factor (frame->window); |
595 | |
596 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
597 | META_CORE_GET_CLIENT_WIDTH, &width, |
598 | META_CORE_GET_CLIENT_HEIGHT, &height, |
599 | META_CORE_GET_FRAME_FLAGS, &flags, |
600 | META_CORE_GET_FRAME_TYPE, &type, |
601 | META_CORE_GET_END); |
602 | |
603 | meta_frames_ensure_layout (frames, frame); |
604 | |
605 | meta_prefs_get_button_layout (&button_layout); |
606 | |
607 | meta_theme_calc_geometry (meta_theme_get_current (), |
608 | type, |
609 | frame->text_height, |
610 | flags, |
611 | width / scale, height / scale, |
612 | &button_layout, |
613 | fgeom); |
614 | } |
615 | |
616 | MetaFrames* |
617 | meta_frames_new (void) |
618 | { |
619 | CdkScreen *screen; |
620 | MetaFrames *frames; |
621 | |
622 | screen = cdk_display_get_default_screen (cdk_display_get_default ()); |
623 | |
624 | frames = g_object_new (META_TYPE_FRAMES(meta_frames_get_type ()), |
625 | "screen", screen, |
626 | "type", CTK_WINDOW_POPUP, |
627 | NULL((void*)0)); |
628 | |
629 | /* Put the window at an arbitrary offscreen location; the one place |
630 | * it can't be is at -100x-100, since the meta_window_new() will |
631 | * mistake it for a window created via meta_create_offscreen_window() |
632 | * and ignore it, and we need this window to get frame-synchronization |
633 | * messages so that CTK+'s style change handling works. |
634 | */ |
635 | ctk_window_move (CTK_WINDOW (frames)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((frames)), ((ctk_window_get_type ())))))), -200, -200); |
636 | ctk_window_resize (CTK_WINDOW (frames)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((frames)), ((ctk_window_get_type ())))))), 1, 1); |
637 | |
638 | return frames; |
639 | } |
640 | |
641 | /* In order to use a style with a window it has to be attached to that |
642 | * window. Actually, the colormaps just have to match, but since CTK+ |
643 | * already takes care of making sure that its cheap to attach a style |
644 | * to multiple windows with the same colormap, we can just go ahead |
645 | * and attach separately for each window. |
646 | */ |
647 | static void |
648 | meta_frames_attach_style (MetaFrames *frames, |
649 | MetaUIFrame *frame) |
650 | { |
651 | gboolean has_frame; |
652 | char *variant = NULL((void*)0); |
653 | if (frame->style != NULL((void*)0)) |
654 | g_object_unref (frame->style); |
655 | |
656 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
657 | frame->xwindow, |
658 | META_CORE_WINDOW_HAS_FRAME, &has_frame, |
659 | META_CORE_GET_THEME_VARIANT, &variant, |
660 | META_CORE_GET_END); |
661 | |
662 | if (variant == NULL((void*)0) || strcmp(variant, "normal") == 0) |
663 | frame->style = g_object_ref (frames->normal_style)((__typeof__ (frames->normal_style)) (g_object_ref) (frames ->normal_style)); |
664 | else |
665 | frame->style = g_object_ref (meta_frames_get_theme_variant (frames,((__typeof__ (meta_frames_get_theme_variant (frames, variant) )) (g_object_ref) (meta_frames_get_theme_variant (frames, variant ))) |
666 | variant))((__typeof__ (meta_frames_get_theme_variant (frames, variant) )) (g_object_ref) (meta_frames_get_theme_variant (frames, variant ))); |
667 | } |
668 | |
669 | void |
670 | meta_frames_manage_window (MetaFrames *frames, |
671 | Window xwindow, |
672 | CdkWindow *window) |
673 | { |
674 | MetaUIFrame *frame; |
675 | |
676 | g_assert (window)do { if (window) ; else g_assertion_message_expr ("croma", "ui/frames.c" , 676, ((const char*) (__func__)), "window"); } while (0); |
677 | |
678 | frame = g_new (MetaUIFrame, 1)((MetaUIFrame *) g_malloc_n ((1), sizeof (MetaUIFrame))); |
679 | |
680 | frame->window = window; |
681 | |
682 | cdk_window_set_user_data (frame->window, frames); |
683 | |
684 | frame->style = NULL((void*)0); |
685 | |
686 | /* Don't set event mask here, it's in frame.c */ |
687 | |
688 | frame->xwindow = xwindow; |
689 | frame->cache_style = NULL((void*)0); |
690 | frame->text_layout = NULL((void*)0); |
691 | frame->text_height = -1; |
692 | frame->title = NULL((void*)0); |
693 | frame->expose_delayed = FALSE(0); |
694 | frame->shape_applied = FALSE(0); |
695 | frame->prelit_control = META_FRAME_CONTROL_NONE; |
696 | |
697 | meta_core_grab_buttons (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
698 | |
699 | g_hash_table_replace (frames->frames, &frame->xwindow, frame); |
700 | } |
701 | |
702 | void |
703 | meta_frames_unmanage_window (MetaFrames *frames, |
704 | Window xwindow) |
705 | { |
706 | MetaUIFrame *frame; |
707 | |
708 | clear_tip (frames); |
709 | |
710 | frame = g_hash_table_lookup (frames->frames, &xwindow); |
711 | |
712 | if (frame) |
713 | { |
714 | /* invalidating all caches ensures the frame |
715 | * is not actually referenced anymore |
716 | */ |
717 | invalidate_all_caches (frames); |
718 | |
719 | /* restore the cursor */ |
720 | meta_core_set_screen_cursor (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
721 | frame->xwindow, |
722 | META_CURSOR_DEFAULT); |
723 | |
724 | cdk_window_set_user_data (frame->window, NULL((void*)0)); |
725 | |
726 | if (frames->last_motion_frame == frame) |
727 | frames->last_motion_frame = NULL((void*)0); |
728 | |
729 | g_hash_table_remove (frames->frames, &frame->xwindow); |
730 | |
731 | g_object_unref (frame->style); |
732 | |
733 | cdk_window_destroy (frame->window); |
734 | |
735 | if (frame->text_layout) |
736 | g_object_unref (G_OBJECT (frame->text_layout)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((frame->text_layout)), (((GType) ((20) << (2)))) ))))); |
737 | |
738 | if (frame->title) |
739 | g_free (frame->title); |
740 | |
741 | g_free (frame); |
742 | } |
743 | else |
744 | meta_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow); |
745 | } |
746 | |
747 | static MetaUIFrame* |
748 | meta_frames_lookup_window (MetaFrames *frames, |
749 | Window xwindow) |
750 | { |
751 | MetaUIFrame *frame; |
752 | |
753 | frame = g_hash_table_lookup (frames->frames, &xwindow); |
754 | |
755 | return frame; |
756 | } |
757 | |
758 | static void |
759 | meta_ui_frame_get_borders (MetaFrames *frames, |
760 | MetaUIFrame *frame, |
761 | MetaFrameBorders *borders) |
762 | { |
763 | MetaFrameFlags flags; |
764 | MetaFrameType type; |
765 | gint scale; |
766 | |
767 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
768 | META_CORE_GET_FRAME_FLAGS, &flags, |
769 | META_CORE_GET_FRAME_TYPE, &type, |
770 | META_CORE_GET_END); |
771 | |
772 | g_return_if_fail (type < META_FRAME_TYPE_LAST)do { if ((type < META_FRAME_TYPE_LAST)) { } else { g_return_if_fail_warning ("croma", ((const char*) (__func__)), "type < META_FRAME_TYPE_LAST" ); return; } } while (0); |
773 | |
774 | scale = cdk_window_get_scale_factor (frame->window); |
775 | |
776 | meta_frames_ensure_layout (frames, frame); |
777 | |
778 | /* We can't get the full geometry, because that depends on |
779 | * the client window size and probably we're being called |
780 | * by the core move/resize code to decide on the client |
781 | * window size |
782 | */ |
783 | meta_theme_get_frame_borders (meta_theme_get_current (), |
784 | type, |
785 | frame->text_height, |
786 | flags, |
787 | borders); |
788 | |
789 | /* Scale frame geometry to ensure proper frame position */ |
790 | borders->visible.top *= scale; |
791 | borders->visible.bottom *= scale; |
792 | borders->visible.left *= scale; |
793 | borders->visible.right *= scale; |
794 | |
795 | borders->invisible.top *= scale; |
796 | borders->invisible.bottom *= scale; |
797 | borders->invisible.left *= scale; |
798 | borders->invisible.right *= scale; |
799 | |
800 | borders->total.top *= scale; |
801 | borders->total.bottom *= scale; |
802 | borders->total.left *= scale; |
803 | borders->total.right *= scale; |
804 | } |
805 | |
806 | void |
807 | meta_frames_get_borders (MetaFrames *frames, |
808 | Window xwindow, |
809 | MetaFrameBorders *borders) |
810 | { |
811 | MetaUIFrame *frame; |
812 | |
813 | frame = meta_frames_lookup_window (frames, xwindow); |
814 | |
815 | if (frame == NULL((void*)0)) |
816 | g_error ("No such frame 0x%lx\n", xwindow); |
817 | |
818 | meta_ui_frame_get_borders (frames, frame, borders); |
819 | } |
820 | |
821 | static void |
822 | meta_ui_frame_get_corner_radiuses (MetaFrames *frames, |
823 | MetaUIFrame *frame, |
824 | float *top_left, |
825 | float *top_right, |
826 | float *bottom_left, |
827 | float *bottom_right) |
828 | { |
829 | MetaFrameGeometry fgeom; |
830 | |
831 | meta_frames_calc_geometry (frames, frame, &fgeom); |
832 | |
833 | /* For compatibility with the code in get_visible_rect(), there's |
834 | * a mysterious sqrt() added to the corner radiuses: |
835 | * |
836 | * const float radius = sqrt(corner) + corner; |
837 | * |
838 | * It's unclear why the radius is calculated like this, but we |
839 | * need to be consistent with it. |
840 | */ |
841 | |
842 | if (top_left) |
843 | *top_left = fgeom.top_left_corner_rounded_radius + sqrt(fgeom.top_left_corner_rounded_radius); |
844 | if (top_right) |
845 | *top_right = fgeom.top_right_corner_rounded_radius + sqrt(fgeom.top_right_corner_rounded_radius); |
846 | if (bottom_left) |
847 | *bottom_left = fgeom.bottom_left_corner_rounded_radius + sqrt(fgeom.bottom_left_corner_rounded_radius); |
848 | if (bottom_right) |
849 | *bottom_right = fgeom.bottom_right_corner_rounded_radius + sqrt(fgeom.bottom_right_corner_rounded_radius); |
850 | } |
851 | |
852 | void |
853 | meta_frames_get_corner_radiuses (MetaFrames *frames, |
854 | Window xwindow, |
855 | float *top_left, |
856 | float *top_right, |
857 | float *bottom_left, |
858 | float *bottom_right) |
859 | { |
860 | MetaUIFrame *frame; |
861 | |
862 | frame = meta_frames_lookup_window (frames, xwindow); |
863 | |
864 | meta_ui_frame_get_corner_radiuses (frames, frame, top_left, top_right, |
865 | bottom_left, bottom_right); |
866 | } |
867 | |
868 | #ifdef HAVE_SHAPE |
869 | static void |
870 | apply_cairo_region_to_window (Display *display, |
871 | Window xwindow, |
872 | cairo_region_t *region, |
873 | int op) |
874 | { |
875 | int n_rects, i; |
876 | XRectangle *rects; |
877 | |
878 | n_rects = cairo_region_num_rectangles (region); |
879 | rects = g_new (XRectangle, n_rects)((XRectangle *) g_malloc_n ((n_rects), sizeof (XRectangle))); |
880 | |
881 | for (i = 0; i < n_rects; i++) |
882 | { |
883 | cairo_rectangle_int_t rect; |
884 | |
885 | cairo_region_get_rectangle (region, i, &rect); |
886 | |
887 | rects[i].x = rect.x; |
888 | rects[i].y = rect.y; |
889 | rects[i].width = rect.width; |
890 | rects[i].height = rect.height; |
891 | } |
892 | |
893 | XShapeCombineRectangles (display, xwindow, |
894 | ShapeBounding0, 0, 0, rects, n_rects, |
895 | op, YXBanded3); |
896 | |
897 | g_free (rects); |
898 | } |
899 | #endif |
900 | |
901 | /* The client rectangle surrounds client window; it subtracts both |
902 | * the visible and invisible borders from the frame window's size. |
903 | */ |
904 | static void |
905 | get_client_rect (MetaFrameGeometry *fgeom, |
906 | int window_width, |
907 | int window_height, |
908 | cairo_rectangle_int_t *rect) |
909 | { |
910 | rect->x = fgeom->borders.total.left; |
911 | rect->y = fgeom->borders.total.top; |
912 | rect->width = window_width - fgeom->borders.total.right - rect->x; |
913 | rect->height = window_height - fgeom->borders.total.bottom - rect->y; |
914 | } |
915 | |
916 | /* The visible frame rectangle surrounds the visible portion of the |
917 | * frame window; it subtracts only the invisible borders from the frame |
918 | * window's size. |
919 | */ |
920 | static void |
921 | get_visible_frame_rect (MetaFrameGeometry *fgeom, |
922 | int window_width, |
923 | int window_height, |
924 | cairo_rectangle_int_t *rect) |
925 | { |
926 | rect->x = fgeom->borders.invisible.left; |
927 | rect->y = fgeom->borders.invisible.top; |
928 | rect->width = window_width - fgeom->borders.invisible.right - rect->x; |
929 | rect->height = window_height - fgeom->borders.invisible.bottom - rect->y; |
930 | } |
931 | |
932 | static cairo_region_t * |
933 | get_visible_region (MetaFrames *frames, |
934 | MetaUIFrame *frame, |
935 | MetaFrameGeometry *fgeom, |
936 | int window_width, |
937 | int window_height) |
938 | { |
939 | cairo_region_t *corners_region; |
940 | cairo_region_t *visible_region; |
941 | cairo_rectangle_int_t rect; |
942 | cairo_rectangle_int_t frame_rect; |
943 | gint scale; |
944 | |
945 | corners_region = cairo_region_create (); |
946 | scale = cdk_window_get_scale_factor (frame->window); |
947 | |
948 | fgeom->borders.invisible.top *= scale; |
949 | fgeom->borders.invisible.bottom *= scale; |
950 | fgeom->borders.invisible.left *= scale; |
951 | fgeom->borders.invisible.right *= scale; |
952 | |
953 | get_visible_frame_rect (fgeom, window_width, window_height, &frame_rect); |
954 | |
955 | if (fgeom->top_left_corner_rounded_radius != 0) |
956 | { |
957 | const int corner = fgeom->top_left_corner_rounded_radius * scale; |
958 | const float radius = sqrt(corner) + corner; |
959 | int i; |
960 | |
961 | for (i=0; i<corner; i++) |
962 | { |
963 | const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); |
964 | rect.x = frame_rect.x; |
965 | rect.y = frame_rect.y + i; |
966 | rect.width = width; |
967 | rect.height = 1; |
968 | |
969 | cairo_region_union_rectangle (corners_region, &rect); |
970 | } |
971 | } |
972 | |
973 | if (fgeom->top_right_corner_rounded_radius != 0) |
974 | { |
975 | const int corner = fgeom->top_right_corner_rounded_radius * scale; |
976 | const float radius = sqrt(corner) + corner; |
977 | int i; |
978 | |
979 | for (i=0; i<corner; i++) |
980 | { |
981 | const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); |
982 | rect.x = frame_rect.x + frame_rect.width - width; |
983 | rect.y = frame_rect.y + i; |
984 | rect.width = width; |
985 | rect.height = 1; |
986 | |
987 | cairo_region_union_rectangle (corners_region, &rect); |
988 | } |
989 | } |
990 | |
991 | if (fgeom->bottom_left_corner_rounded_radius != 0) |
992 | { |
993 | const int corner = fgeom->bottom_left_corner_rounded_radius * scale; |
994 | const float radius = sqrt(corner) + corner; |
995 | int i; |
996 | |
997 | for (i=0; i<corner; i++) |
998 | { |
999 | const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); |
1000 | rect.x = frame_rect.x; |
1001 | rect.y = frame_rect.y + frame_rect.height - i - 1; |
1002 | rect.width = width; |
1003 | rect.height = 1; |
1004 | |
1005 | cairo_region_union_rectangle (corners_region, &rect); |
1006 | } |
1007 | } |
1008 | |
1009 | if (fgeom->bottom_right_corner_rounded_radius != 0) |
1010 | { |
1011 | const int corner = fgeom->bottom_right_corner_rounded_radius * scale; |
1012 | const float radius = sqrt(corner) + corner; |
1013 | int i; |
1014 | |
1015 | for (i=0; i<corner; i++) |
1016 | { |
1017 | const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); |
1018 | rect.x = frame_rect.x + frame_rect.width - width; |
1019 | rect.y = frame_rect.y + frame_rect.height - i - 1; |
1020 | rect.width = width; |
1021 | rect.height = 1; |
1022 | |
1023 | cairo_region_union_rectangle (corners_region, &rect); |
1024 | } |
1025 | } |
1026 | |
1027 | visible_region = cairo_region_create_rectangle (&frame_rect); |
1028 | cairo_region_subtract (visible_region, corners_region); |
1029 | cairo_region_destroy (corners_region); |
1030 | |
1031 | return visible_region; |
1032 | } |
1033 | |
1034 | static cairo_region_t * |
1035 | get_client_region (MetaFrameGeometry *fgeom, |
1036 | int window_width, |
1037 | int window_height) |
1038 | { |
1039 | cairo_rectangle_int_t rect; |
1040 | |
1041 | rect.x = fgeom->borders.total.left; |
1042 | rect.y = fgeom->borders.total.top; |
1043 | rect.width = window_width - fgeom->borders.total.right - rect.x; |
1044 | rect.height = window_height - fgeom->borders.total.bottom - rect.y; |
1045 | |
1046 | return cairo_region_create_rectangle (&rect); |
1047 | } |
1048 | |
1049 | static cairo_region_t * |
1050 | get_frame_region (int window_width, |
1051 | int window_height) |
1052 | { |
1053 | cairo_rectangle_int_t rect; |
1054 | |
1055 | rect.x = 0; |
1056 | rect.y = 0; |
1057 | rect.width = window_width; |
1058 | rect.height = window_height; |
1059 | |
1060 | return cairo_region_create_rectangle (&rect); |
1061 | } |
1062 | |
1063 | void |
1064 | meta_frames_apply_shapes (MetaFrames *frames, |
1065 | Window xwindow, |
1066 | int new_window_width, |
1067 | int new_window_height, |
1068 | gboolean window_has_shape) |
1069 | { |
1070 | #ifdef HAVE_SHAPE |
1071 | /* Apply shapes as if window had new_window_width, new_window_height */ |
1072 | MetaUIFrame *frame; |
1073 | MetaFrameGeometry fgeom; |
1074 | cairo_region_t *window_region; |
1075 | Display *display; |
1076 | gboolean compositing_manager; |
1077 | |
1078 | frame = meta_frames_lookup_window (frames, xwindow); |
1079 | g_return_if_fail (frame != NULL)do { if ((frame != ((void*)0))) { } else { g_return_if_fail_warning ("croma", ((const char*) (__func__)), "frame != NULL"); return ; } } while (0); |
1080 | |
1081 | display = CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())); |
1082 | |
1083 | if (frame->shape_applied) |
1084 | { |
1085 | meta_topicmeta_topic_real (META_DEBUG_SHAPES, |
1086 | "Unsetting shape mask on frame 0x%lx\n", |
1087 | frame->xwindow); |
1088 | |
1089 | XShapeCombineMask (display, frame->xwindow, |
1090 | ShapeBounding0, 0, 0, None0L, ShapeSet0); |
1091 | frame->shape_applied = FALSE(0); |
1092 | } |
1093 | |
1094 | meta_frames_calc_geometry (frames, frame, &fgeom); |
1095 | |
1096 | compositing_manager = meta_prefs_get_compositing_manager (); |
1097 | |
1098 | if (!window_has_shape && compositing_manager) |
1099 | return; |
1100 | |
1101 | window_region = get_visible_region (frames, |
1102 | frame, |
1103 | &fgeom, |
1104 | new_window_width, |
1105 | new_window_height); |
1106 | |
1107 | if (window_has_shape) |
1108 | { |
1109 | /* The client window is oclock or something and has a shape |
1110 | * mask. To avoid a round trip to get its shape region, we |
1111 | * create a fake window that's never mapped, build up our shape |
1112 | * on that, then combine. Wasting the window is assumed cheaper |
1113 | * than a round trip, but who really knows for sure. |
1114 | */ |
1115 | XSetWindowAttributes attrs; |
1116 | Window shape_window; |
1117 | Window client_window; |
1118 | cairo_region_t *frame_region; |
1119 | cairo_region_t *client_region; |
1120 | cairo_region_t *tmp_region; |
1121 | CdkScreen *screen; |
1122 | int screen_number; |
1123 | |
1124 | meta_topicmeta_topic_real (META_DEBUG_SHAPES, |
1125 | "Frame 0x%lx needs to incorporate client shape\n", |
1126 | frame->xwindow); |
1127 | |
1128 | screen = ctk_widget_get_screen (CTK_WIDGET (frames)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((frames)), ((ctk_widget_get_type ()))))))); |
1129 | screen_number = cdk_x11_screen_get_screen_number (screen); |
1130 | |
1131 | attrs.override_redirect = True1; |
1132 | |
1133 | shape_window = XCreateWindow (display, |
1134 | RootWindow (display, screen_number)((&((_XPrivDisplay)(display))->screens[screen_number]) ->root), |
1135 | -5000, -5000, |
1136 | new_window_width, |
1137 | new_window_height, |
1138 | 0, |
1139 | CopyFromParent0L, |
1140 | CopyFromParent0L, |
1141 | (Visual *)CopyFromParent0L, |
1142 | CWOverrideRedirect(1L<<9), |
1143 | &attrs); |
1144 | |
1145 | /* Copy the client's shape to the temporary shape_window */ |
1146 | meta_core_get (display, frame->xwindow, |
1147 | META_CORE_GET_CLIENT_XWINDOW, &client_window, |
1148 | META_CORE_GET_END); |
1149 | |
1150 | XShapeCombineShape (display, shape_window, ShapeBounding0, |
1151 | fgeom.borders.total.left, |
1152 | fgeom.borders.total.top, |
1153 | client_window, |
1154 | ShapeBounding0, |
1155 | ShapeSet0); |
1156 | |
1157 | /* Punch the client area out of the normal frame shape, |
1158 | * then union it with the shape_window's existing shape |
1159 | */ |
1160 | frame_region = get_frame_region (new_window_width, |
1161 | new_window_height); |
1162 | client_region = get_client_region (&fgeom, |
1163 | new_window_width, |
1164 | new_window_height); |
1165 | |
1166 | tmp_region = compositing_manager ? frame_region : window_region; |
1167 | |
1168 | cairo_region_subtract (tmp_region, client_region); |
1169 | |
1170 | cairo_region_destroy (client_region); |
1171 | |
1172 | apply_cairo_region_to_window (display, shape_window, |
1173 | tmp_region, ShapeUnion1); |
1174 | |
1175 | cairo_region_destroy (frame_region); |
1176 | |
1177 | /* Now copy shape_window shape to the real frame */ |
1178 | XShapeCombineShape (display, frame->xwindow, ShapeBounding0, |
1179 | 0, 0, |
1180 | shape_window, |
1181 | ShapeBounding0, |
1182 | ShapeSet0); |
1183 | |
1184 | XDestroyWindow (display, shape_window); |
1185 | } |
1186 | else |
1187 | { |
1188 | /* No shape on the client, so just do simple stuff */ |
1189 | |
1190 | meta_topicmeta_topic_real (META_DEBUG_SHAPES, |
1191 | "Frame 0x%lx has shaped corners\n", |
1192 | frame->xwindow); |
1193 | |
1194 | if (!compositing_manager) |
1195 | apply_cairo_region_to_window (display, |
1196 | frame->xwindow, window_region, |
1197 | ShapeSet0); |
1198 | } |
1199 | |
1200 | frame->shape_applied = TRUE(!(0)); |
1201 | |
1202 | cairo_region_destroy (window_region); |
1203 | #endif /* HAVE_SHAPE */ |
1204 | } |
1205 | |
1206 | cairo_region_t * |
1207 | meta_frames_get_frame_bounds (MetaFrames *frames, |
1208 | Window xwindow, |
1209 | int window_width, |
1210 | int window_height) |
1211 | { |
1212 | MetaUIFrame *frame; |
1213 | MetaFrameGeometry fgeom; |
1214 | |
1215 | frame = meta_frames_lookup_window (frames, xwindow); |
1216 | g_return_val_if_fail (frame != NULL, NULL)do { if ((frame != ((void*)0))) { } else { g_return_if_fail_warning ("croma", ((const char*) (__func__)), "frame != NULL"); return (((void*)0)); } } while (0); |
1217 | |
1218 | meta_frames_calc_geometry (frames, frame, &fgeom); |
1219 | |
1220 | return get_visible_region (frames, |
1221 | frame, |
1222 | &fgeom, |
1223 | window_width, |
1224 | window_height); |
1225 | } |
1226 | |
1227 | void |
1228 | meta_frames_move_resize_frame (MetaFrames *frames, |
1229 | Window xwindow, |
1230 | int x, |
1231 | int y, |
1232 | int width, |
1233 | int height) |
1234 | { |
1235 | MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow); |
1236 | int old_width, old_height; |
1237 | gint scale; |
1238 | |
1239 | old_width = cdk_window_get_width (frame->window); |
1240 | old_height = cdk_window_get_height (frame->window); |
1241 | |
1242 | scale = cdk_window_get_scale_factor (frame->window); |
1243 | |
1244 | cdk_window_move_resize (frame->window, x / scale, y / scale, width / scale, height / scale); |
1245 | |
1246 | if (old_width != width || old_height != height) |
1247 | invalidate_whole_window (frames, frame); |
1248 | } |
1249 | |
1250 | void |
1251 | meta_frames_queue_draw (MetaFrames *frames, |
1252 | Window xwindow) |
1253 | { |
1254 | MetaUIFrame *frame; |
1255 | |
1256 | frame = meta_frames_lookup_window (frames, xwindow); |
1257 | |
1258 | invalidate_whole_window (frames, frame); |
1259 | } |
1260 | |
1261 | void |
1262 | meta_frames_set_title (MetaFrames *frames, |
1263 | Window xwindow, |
1264 | const char *title) |
1265 | { |
1266 | MetaUIFrame *frame; |
1267 | |
1268 | frame = meta_frames_lookup_window (frames, xwindow); |
1269 | |
1270 | g_assert (frame)do { if (frame) ; else g_assertion_message_expr ("croma", "ui/frames.c" , 1270, ((const char*) (__func__)), "frame"); } while (0); |
1271 | |
1272 | g_free (frame->title); |
1273 | frame->title = g_strdup (title); |
1274 | |
1275 | g_clear_object (&frame->text_layout)do { _Static_assert (sizeof *((&frame->text_layout)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&frame->text_layout))) _pp = ((&frame->text_layout )); __typeof__ (*((&frame->text_layout))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while (0); |
1276 | |
1277 | invalidate_whole_window (frames, frame); |
1278 | } |
1279 | |
1280 | void |
1281 | meta_frames_update_frame_style (MetaFrames *frames, |
1282 | Window xwindow) |
1283 | { |
1284 | MetaUIFrame *frame; |
1285 | |
1286 | frame = meta_frames_lookup_window (frames, xwindow); |
1287 | |
1288 | g_assert (frame)do { if (frame) ; else g_assertion_message_expr ("croma", "ui/frames.c" , 1288, ((const char*) (__func__)), "frame"); } while (0); |
1289 | |
1290 | meta_frames_attach_style (frames, frame); |
1291 | invalidate_whole_window (frames, frame); |
1292 | } |
1293 | |
1294 | void |
1295 | meta_frames_repaint_frame (MetaFrames *frames, |
1296 | Window xwindow) |
1297 | { |
1298 | MetaUIFrame *frame; |
1299 | |
1300 | frame = meta_frames_lookup_window (frames, xwindow); |
1301 | |
1302 | g_assert (frame)do { if (frame) ; else g_assertion_message_expr ("croma", "ui/frames.c" , 1302, ((const char*) (__func__)), "frame"); } while (0); |
1303 | |
1304 | /* repaint everything, so the other frame don't |
1305 | * lag behind if they are exposed |
1306 | */ |
1307 | cdk_window_process_all_updates (); |
1308 | } |
1309 | |
1310 | static void |
1311 | show_tip_now (MetaFrames *frames) |
1312 | { |
1313 | const char *tiptext; |
1314 | MetaUIFrame *frame; |
1315 | int x, y, root_x, root_y; |
1316 | Window root, child; |
1317 | guint mask; |
1318 | MetaFrameControl control; |
1319 | |
1320 | frame = frames->last_motion_frame; |
1321 | if (frame == NULL((void*)0)) |
1322 | return; |
1323 | |
1324 | XQueryPointer (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
1325 | frame->xwindow, |
1326 | &root, &child, |
1327 | &root_x, &root_y, |
1328 | &x, &y, |
1329 | &mask); |
1330 | |
1331 | control = get_control (frames, frame, x, y); |
1332 | |
1333 | tiptext = NULL((void*)0); |
1334 | switch (control) |
1335 | { |
1336 | case META_FRAME_CONTROL_TITLE: |
1337 | break; |
1338 | case META_FRAME_CONTROL_DELETE: |
1339 | tiptext = _("Close Window")dgettext ("croma", "Close Window"); |
1340 | break; |
1341 | case META_FRAME_CONTROL_MENU: |
1342 | tiptext = _("Window Menu")dgettext ("croma", "Window Menu"); |
1343 | break; |
1344 | case META_FRAME_CONTROL_APPMENU: |
1345 | tiptext = _("Window App Menu")dgettext ("croma", "Window App Menu"); |
1346 | break; |
1347 | case META_FRAME_CONTROL_MINIMIZE: |
1348 | tiptext = _("Minimize Window")dgettext ("croma", "Minimize Window"); |
1349 | break; |
1350 | case META_FRAME_CONTROL_MAXIMIZE: |
1351 | tiptext = _("Maximize Window")dgettext ("croma", "Maximize Window"); |
1352 | break; |
1353 | case META_FRAME_CONTROL_UNMAXIMIZE: |
1354 | tiptext = _("Restore Window")dgettext ("croma", "Restore Window"); |
1355 | break; |
1356 | case META_FRAME_CONTROL_SHADE: |
1357 | tiptext = _("Roll Up Window")dgettext ("croma", "Roll Up Window"); |
1358 | break; |
1359 | case META_FRAME_CONTROL_UNSHADE: |
1360 | tiptext = _("Unroll Window")dgettext ("croma", "Unroll Window"); |
1361 | break; |
1362 | case META_FRAME_CONTROL_ABOVE: |
1363 | tiptext = _("Keep Window On Top")dgettext ("croma", "Keep Window On Top"); |
1364 | break; |
1365 | case META_FRAME_CONTROL_UNABOVE: |
1366 | tiptext = _("Remove Window From Top")dgettext ("croma", "Remove Window From Top"); |
1367 | break; |
1368 | case META_FRAME_CONTROL_STICK: |
1369 | tiptext = _("Always On Visible Workspace")dgettext ("croma", "Always On Visible Workspace"); |
1370 | break; |
1371 | case META_FRAME_CONTROL_UNSTICK: |
1372 | tiptext = _("Put Window On Only One Workspace")dgettext ("croma", "Put Window On Only One Workspace"); |
1373 | break; |
1374 | case META_FRAME_CONTROL_RESIZE_SE: |
1375 | break; |
1376 | case META_FRAME_CONTROL_RESIZE_S: |
1377 | break; |
1378 | case META_FRAME_CONTROL_RESIZE_SW: |
1379 | break; |
1380 | case META_FRAME_CONTROL_RESIZE_N: |
1381 | break; |
1382 | case META_FRAME_CONTROL_RESIZE_NE: |
1383 | break; |
1384 | case META_FRAME_CONTROL_RESIZE_NW: |
1385 | break; |
1386 | case META_FRAME_CONTROL_RESIZE_W: |
1387 | break; |
1388 | case META_FRAME_CONTROL_RESIZE_E: |
1389 | break; |
1390 | case META_FRAME_CONTROL_NONE: |
1391 | break; |
1392 | case META_FRAME_CONTROL_CLIENT_AREA: |
1393 | break; |
1394 | } |
1395 | |
1396 | if (tiptext) |
1397 | { |
1398 | MetaFrameGeometry fgeom; |
1399 | CdkRectangle *rect; |
1400 | int dx, dy, scale; |
1401 | |
1402 | meta_frames_calc_geometry (frames, frame, &fgeom); |
1403 | |
1404 | rect = control_rect (control, &fgeom); |
1405 | scale = cdk_window_get_scale_factor (frame->window); |
1406 | |
1407 | /* get conversion delta for root-to-frame coords */ |
1408 | dx = (root_x - x) / scale; |
1409 | dy = (root_y - y) / scale; |
1410 | |
1411 | /* Align the tooltip to the button right end if RTL */ |
1412 | if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) |
1413 | dx += rect->width; |
1414 | |
1415 | meta_fixed_tip_show (rect->x + dx, |
1416 | rect->y + rect->height + 2 + dy, |
1417 | tiptext); |
1418 | } |
1419 | } |
1420 | |
1421 | static gboolean |
1422 | tip_timeout_func (gpointer data) |
1423 | { |
1424 | MetaFrames *frames; |
1425 | |
1426 | frames = data; |
1427 | |
1428 | show_tip_now (frames); |
1429 | |
1430 | frames->tooltip_timeout = 0; |
1431 | |
1432 | return FALSE(0); |
1433 | } |
1434 | |
1435 | #define TIP_DELAY450 450 |
1436 | static void |
1437 | queue_tip (MetaFrames *frames) |
1438 | { |
1439 | clear_tip (frames); |
1440 | |
1441 | frames->tooltip_timeout = g_timeout_add (TIP_DELAY450, |
1442 | tip_timeout_func, |
1443 | frames); |
1444 | } |
1445 | |
1446 | static void |
1447 | clear_tip (MetaFrames *frames) |
1448 | { |
1449 | if (frames->tooltip_timeout) |
1450 | { |
1451 | g_source_remove (frames->tooltip_timeout); |
1452 | frames->tooltip_timeout = 0; |
1453 | } |
1454 | meta_fixed_tip_hide (); |
1455 | } |
1456 | |
1457 | static void |
1458 | redraw_control (MetaFrames *frames, |
1459 | MetaUIFrame *frame, |
1460 | MetaFrameControl control) |
1461 | { |
1462 | MetaFrameGeometry fgeom; |
1463 | CdkRectangle *rect; |
1464 | |
1465 | meta_frames_calc_geometry (frames, frame, &fgeom); |
1466 | |
1467 | rect = control_rect (control, &fgeom); |
1468 | |
1469 | cdk_window_invalidate_rect (frame->window, rect, FALSE(0)); |
1470 | invalidate_cache (frames, frame); |
1471 | } |
1472 | |
1473 | static gboolean |
1474 | meta_frame_titlebar_event (MetaUIFrame *frame, |
1475 | CdkEventButton *event, |
1476 | int action) |
1477 | { |
1478 | MetaFrameFlags flags; |
1479 | |
1480 | switch (action) |
1481 | { |
1482 | case META_ACTION_TITLEBAR_TOGGLE_SHADE: |
1483 | { |
1484 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
1485 | META_CORE_GET_FRAME_FLAGS, &flags, |
1486 | META_CORE_GET_END); |
1487 | |
1488 | if (flags & META_FRAME_ALLOWS_SHADE) |
1489 | { |
1490 | if (flags & META_FRAME_SHADED) |
1491 | meta_core_unshade (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
1492 | frame->xwindow, |
1493 | event->time); |
1494 | else |
1495 | meta_core_shade (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
1496 | frame->xwindow, |
1497 | event->time); |
1498 | } |
1499 | } |
1500 | break; |
1501 | |
1502 | case META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE: |
1503 | { |
1504 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
1505 | META_CORE_GET_FRAME_FLAGS, &flags, |
1506 | META_CORE_GET_END); |
1507 | |
1508 | if (flags & META_FRAME_ALLOWS_MAXIMIZE) |
1509 | { |
1510 | meta_core_toggle_maximize (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1511 | } |
1512 | } |
1513 | break; |
1514 | |
1515 | case META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_HORIZONTALLY: |
1516 | { |
1517 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
1518 | META_CORE_GET_FRAME_FLAGS, &flags, |
1519 | META_CORE_GET_END); |
1520 | |
1521 | if (flags & META_FRAME_ALLOWS_MAXIMIZE) |
1522 | { |
1523 | meta_core_toggle_maximize_horizontally (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1524 | } |
1525 | } |
1526 | break; |
1527 | |
1528 | case META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_VERTICALLY: |
1529 | { |
1530 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
1531 | META_CORE_GET_FRAME_FLAGS, &flags, |
1532 | META_CORE_GET_END); |
1533 | |
1534 | if (flags & META_FRAME_ALLOWS_MAXIMIZE) |
1535 | { |
1536 | meta_core_toggle_maximize_vertically (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1537 | } |
1538 | } |
1539 | break; |
1540 | |
1541 | case META_ACTION_TITLEBAR_MINIMIZE: |
1542 | { |
1543 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
1544 | META_CORE_GET_FRAME_FLAGS, &flags, |
1545 | META_CORE_GET_END); |
1546 | |
1547 | if (flags & META_FRAME_ALLOWS_MINIMIZE) |
1548 | { |
1549 | meta_core_minimize (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1550 | } |
1551 | } |
1552 | break; |
1553 | |
1554 | case META_ACTION_TITLEBAR_NONE: |
1555 | /* Yaay, a sane user that doesn't use that other weird crap! */ |
1556 | break; |
1557 | |
1558 | case META_ACTION_TITLEBAR_LOWER: |
1559 | meta_core_user_lower_and_unfocus (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
1560 | frame->xwindow, |
1561 | event->time); |
1562 | break; |
1563 | |
1564 | case META_ACTION_TITLEBAR_MENU: |
1565 | meta_core_show_window_menu (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
1566 | frame->xwindow, |
1567 | event->x_root, |
1568 | event->y_root, |
1569 | event->button, |
1570 | event->time); |
1571 | break; |
1572 | |
1573 | case META_ACTION_TITLEBAR_LAST: |
1574 | break; |
1575 | } |
1576 | |
1577 | return TRUE(!(0)); |
1578 | } |
1579 | |
1580 | static gboolean |
1581 | meta_frame_double_click_event (MetaUIFrame *frame, |
1582 | CdkEventButton *event) |
1583 | { |
1584 | int action = meta_prefs_get_action_double_click_titlebar (); |
1585 | |
1586 | return meta_frame_titlebar_event (frame, event, action); |
1587 | } |
1588 | |
1589 | static gboolean |
1590 | meta_frame_middle_click_event (MetaUIFrame *frame, |
1591 | CdkEventButton *event) |
1592 | { |
1593 | int action = meta_prefs_get_action_middle_click_titlebar(); |
1594 | |
1595 | return meta_frame_titlebar_event (frame, event, action); |
1596 | } |
1597 | |
1598 | static gboolean |
1599 | meta_frame_right_click_event(MetaUIFrame *frame, |
1600 | CdkEventButton *event) |
1601 | { |
1602 | int action = meta_prefs_get_action_right_click_titlebar(); |
1603 | |
1604 | return meta_frame_titlebar_event (frame, event, action); |
1605 | } |
1606 | |
1607 | static gboolean |
1608 | meta_frames_button_press_event (CtkWidget *widget, |
1609 | CdkEventButton *event) |
1610 | { |
1611 | MetaUIFrame *frame; |
1612 | MetaFrames *frames; |
1613 | MetaFrameControl control; |
1614 | |
1615 | frames = META_FRAMES (widget)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((meta_frames_get_type ())))))); |
1616 | |
1617 | /* Remember that the display may have already done something with this event. |
1618 | * If so there's probably a GrabOp in effect. |
1619 | */ |
1620 | |
1621 | frame = meta_frames_lookup_window (frames, CDK_WINDOW_XID (event->window)(cdk_x11_window_get_xid (event->window))); |
1622 | if (frame == NULL((void*)0)) |
1623 | return FALSE(0); |
1624 | |
1625 | clear_tip (frames); |
1626 | |
1627 | control = get_control (frames, frame, event->x, event->y); |
1628 | |
1629 | /* focus on click, even if click was on client area */ |
1630 | if (event->button == 1 && |
1631 | !(control == META_FRAME_CONTROL_MINIMIZE || |
1632 | control == META_FRAME_CONTROL_DELETE || |
1633 | control == META_FRAME_CONTROL_MAXIMIZE)) |
1634 | { |
1635 | meta_topicmeta_topic_real (META_DEBUG_FOCUS, |
1636 | "Focusing window with frame 0x%lx due to button 1 press\n", |
1637 | frame->xwindow); |
1638 | meta_core_user_focus (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
1639 | frame->xwindow, |
1640 | event->time); |
1641 | } |
1642 | |
1643 | /* don't do the rest of this if on client area */ |
1644 | if (control == META_FRAME_CONTROL_CLIENT_AREA) |
1645 | return FALSE(0); /* not on the frame, just passed through from client */ |
1646 | |
1647 | /* We want to shade even if we have a GrabOp, since we'll have a move grab |
1648 | * if we double click the titlebar. |
1649 | */ |
1650 | if (control == META_FRAME_CONTROL_TITLE && |
1651 | event->button == 1 && |
1652 | event->type == CDK_2BUTTON_PRESS) |
1653 | { |
1654 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
1655 | return meta_frame_double_click_event (frame, event); |
1656 | } |
1657 | |
1658 | if (meta_core_get_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ()))) != |
1659 | META_GRAB_OP_NONE) |
1660 | return FALSE(0); /* already up to something */ |
1661 | |
1662 | if ((event->button == 1 && |
1663 | (control == META_FRAME_CONTROL_MINIMIZE || |
1664 | control == META_FRAME_CONTROL_DELETE || |
1665 | control == META_FRAME_CONTROL_SHADE || |
1666 | control == META_FRAME_CONTROL_UNSHADE || |
1667 | control == META_FRAME_CONTROL_ABOVE || |
1668 | control == META_FRAME_CONTROL_UNABOVE || |
1669 | control == META_FRAME_CONTROL_STICK || |
1670 | control == META_FRAME_CONTROL_UNSTICK || |
1671 | control == META_FRAME_CONTROL_MENU)) || |
1672 | (control == META_FRAME_CONTROL_MAXIMIZE || |
1673 | control == META_FRAME_CONTROL_UNMAXIMIZE)) |
1674 | { |
1675 | MetaGrabOp op; |
1676 | |
1677 | switch (control) |
1678 | { |
1679 | case META_FRAME_CONTROL_MINIMIZE: |
1680 | op = META_GRAB_OP_CLICKING_MINIMIZE; |
1681 | break; |
1682 | case META_FRAME_CONTROL_MAXIMIZE: |
1683 | op = META_GRAB_OP_CLICKING_MAXIMIZE + event->button - 1; |
1684 | op = op > META_GRAB_OP_CLICKING_MAXIMIZE_HORIZONTAL ? META_GRAB_OP_CLICKING_MAXIMIZE : op; |
1685 | break; |
1686 | case META_FRAME_CONTROL_UNMAXIMIZE: |
1687 | op = META_GRAB_OP_CLICKING_UNMAXIMIZE; |
1688 | break; |
1689 | case META_FRAME_CONTROL_DELETE: |
1690 | op = META_GRAB_OP_CLICKING_DELETE; |
1691 | break; |
1692 | case META_FRAME_CONTROL_MENU: |
1693 | op = META_GRAB_OP_CLICKING_MENU; |
1694 | break; |
1695 | case META_FRAME_CONTROL_APPMENU: |
1696 | op = META_GRAB_OP_CLICKING_APPMENU; |
This statement is never executed | |
1697 | break; |
1698 | case META_FRAME_CONTROL_SHADE: |
1699 | op = META_GRAB_OP_CLICKING_SHADE; |
1700 | break; |
1701 | case META_FRAME_CONTROL_UNSHADE: |
1702 | op = META_GRAB_OP_CLICKING_UNSHADE; |
1703 | break; |
1704 | case META_FRAME_CONTROL_ABOVE: |
1705 | op = META_GRAB_OP_CLICKING_ABOVE; |
1706 | break; |
1707 | case META_FRAME_CONTROL_UNABOVE: |
1708 | op = META_GRAB_OP_CLICKING_UNABOVE; |
1709 | break; |
1710 | case META_FRAME_CONTROL_STICK: |
1711 | op = META_GRAB_OP_CLICKING_STICK; |
1712 | break; |
1713 | case META_FRAME_CONTROL_UNSTICK: |
1714 | op = META_GRAB_OP_CLICKING_UNSTICK; |
1715 | break; |
1716 | default: |
1717 | g_assert_not_reached ()do { g_assertion_message_expr ("croma", "ui/frames.c", 1717, ( (const char*) (__func__)), ((void*)0)); } while (0); |
1718 | op = META_GRAB_OP_NONE; |
1719 | } |
1720 | |
1721 | meta_core_begin_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
1722 | frame->xwindow, |
1723 | op, |
1724 | TRUE(!(0)), |
1725 | TRUE(!(0)), |
1726 | event->button, |
1727 | 0, |
1728 | event->time, |
1729 | event->x_root, |
1730 | event->y_root); |
1731 | |
1732 | frame->prelit_control = control; |
1733 | redraw_control (frames, frame, control); |
1734 | |
1735 | if (op == META_GRAB_OP_CLICKING_MENU) |
1736 | { |
1737 | MetaFrameGeometry fgeom; |
1738 | CdkRectangle *rect; |
1739 | int dx, dy; |
1740 | |
1741 | meta_frames_calc_geometry (frames, frame, &fgeom); |
1742 | |
1743 | rect = control_rect (META_FRAME_CONTROL_MENU, &fgeom); |
1744 | |
1745 | /* get delta to convert to root coords */ |
1746 | dx = event->x_root - event->x; |
1747 | dy = event->y_root - event->y; |
1748 | |
1749 | /* Align to the right end of the menu rectangle if RTL */ |
1750 | if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) |
1751 | dx += rect->width; |
1752 | |
1753 | meta_core_show_window_menu (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
1754 | frame->xwindow, |
1755 | rect->x + dx, |
1756 | rect->y + rect->height + dy, |
1757 | event->button, |
1758 | event->time); |
1759 | } |
1760 | } |
1761 | else if (event->button == 1 && |
1762 | (control == META_FRAME_CONTROL_RESIZE_SE || |
1763 | control == META_FRAME_CONTROL_RESIZE_S || |
1764 | control == META_FRAME_CONTROL_RESIZE_SW || |
1765 | control == META_FRAME_CONTROL_RESIZE_NE || |
1766 | control == META_FRAME_CONTROL_RESIZE_N || |
1767 | control == META_FRAME_CONTROL_RESIZE_NW || |
1768 | control == META_FRAME_CONTROL_RESIZE_E || |
1769 | control == META_FRAME_CONTROL_RESIZE_W)) |
1770 | { |
1771 | MetaGrabOp op; |
1772 | |
1773 | op = META_GRAB_OP_NONE; |
1774 | |
1775 | switch (control) |
1776 | { |
1777 | case META_FRAME_CONTROL_RESIZE_SE: |
1778 | op = META_GRAB_OP_RESIZING_SE; |
1779 | break; |
1780 | case META_FRAME_CONTROL_RESIZE_S: |
1781 | op = META_GRAB_OP_RESIZING_S; |
1782 | break; |
1783 | case META_FRAME_CONTROL_RESIZE_SW: |
1784 | op = META_GRAB_OP_RESIZING_SW; |
1785 | break; |
1786 | case META_FRAME_CONTROL_RESIZE_NE: |
1787 | op = META_GRAB_OP_RESIZING_NE; |
1788 | break; |
1789 | case META_FRAME_CONTROL_RESIZE_N: |
1790 | op = META_GRAB_OP_RESIZING_N; |
1791 | break; |
1792 | case META_FRAME_CONTROL_RESIZE_NW: |
1793 | op = META_GRAB_OP_RESIZING_NW; |
1794 | break; |
1795 | case META_FRAME_CONTROL_RESIZE_E: |
1796 | op = META_GRAB_OP_RESIZING_E; |
1797 | break; |
1798 | case META_FRAME_CONTROL_RESIZE_W: |
1799 | op = META_GRAB_OP_RESIZING_W; |
1800 | break; |
1801 | default: |
1802 | g_assert_not_reached ()do { g_assertion_message_expr ("croma", "ui/frames.c", 1802, ( (const char*) (__func__)), ((void*)0)); } while (0); |
1803 | break; |
1804 | } |
1805 | |
1806 | meta_core_begin_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
1807 | frame->xwindow, |
1808 | op, |
1809 | TRUE(!(0)), |
1810 | TRUE(!(0)), |
1811 | event->button, |
1812 | 0, |
1813 | event->time, |
1814 | event->x_root, |
1815 | event->y_root); |
1816 | } |
1817 | else if (control == META_FRAME_CONTROL_TITLE && |
1818 | event->button == 1) |
1819 | { |
1820 | MetaFrameFlags flags; |
1821 | |
1822 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
1823 | META_CORE_GET_FRAME_FLAGS, &flags, |
1824 | META_CORE_GET_END); |
1825 | |
1826 | if (flags & META_FRAME_ALLOWS_MOVE) |
1827 | { |
1828 | meta_core_begin_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
1829 | frame->xwindow, |
1830 | META_GRAB_OP_MOVING, |
1831 | TRUE(!(0)), |
1832 | TRUE(!(0)), |
1833 | event->button, |
1834 | 0, |
1835 | event->time, |
1836 | event->x_root, |
1837 | event->y_root); |
1838 | } |
1839 | } |
1840 | else if (event->button == 2) |
1841 | { |
1842 | return meta_frame_middle_click_event (frame, event); |
1843 | } |
1844 | else if (event->button == 3) |
1845 | { |
1846 | return meta_frame_right_click_event (frame, event); |
1847 | } |
1848 | |
1849 | return TRUE(!(0)); |
1850 | } |
1851 | |
1852 | void |
1853 | meta_frames_notify_menu_hide (MetaFrames *frames) |
1854 | { |
1855 | if (meta_core_get_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ()))) == |
1856 | META_GRAB_OP_CLICKING_MENU) |
1857 | { |
1858 | Window grab_frame; |
1859 | |
1860 | grab_frame = meta_core_get_grab_frame (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ()))); |
1861 | |
1862 | if (grab_frame != None0L) |
1863 | { |
1864 | MetaUIFrame *frame; |
1865 | |
1866 | frame = meta_frames_lookup_window (frames, grab_frame); |
1867 | |
1868 | if (frame) |
1869 | { |
1870 | redraw_control (frames, frame, |
1871 | META_FRAME_CONTROL_MENU); |
1872 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), CurrentTime0L); |
1873 | } |
1874 | } |
1875 | } |
1876 | } |
1877 | |
1878 | static gboolean |
1879 | meta_frames_button_release_event (CtkWidget *widget, |
1880 | CdkEventButton *event) |
1881 | { |
1882 | MetaUIFrame *frame; |
1883 | MetaFrames *frames; |
1884 | MetaGrabOp op; |
1885 | |
1886 | frames = META_FRAMES (widget)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((meta_frames_get_type ())))))); |
1887 | |
1888 | frame = meta_frames_lookup_window (frames, CDK_WINDOW_XID (event->window)(cdk_x11_window_get_xid (event->window))); |
1889 | if (frame == NULL((void*)0)) |
1890 | return FALSE(0); |
1891 | |
1892 | clear_tip (frames); |
1893 | |
1894 | op = meta_core_get_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ()))); |
1895 | |
1896 | if (op == META_GRAB_OP_NONE) |
1897 | return FALSE(0); |
1898 | |
1899 | /* We only handle the releases we handled the presses for (things |
1900 | * involving frame controls). Window ops that don't require a |
1901 | * frame are handled in the Xlib part of the code, display.c/window.c |
1902 | */ |
1903 | if (frame->xwindow == meta_core_get_grab_frame (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ()))) && |
1904 | ((int) event->button) == meta_core_get_grab_button (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())))) |
1905 | { |
1906 | MetaFrameControl control; |
1907 | |
1908 | control = get_control (frames, frame, event->x, event->y); |
1909 | |
1910 | switch (op) |
1911 | { |
1912 | case META_GRAB_OP_CLICKING_MINIMIZE: |
1913 | if (control == META_FRAME_CONTROL_MINIMIZE) |
1914 | meta_core_minimize (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1915 | |
1916 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
1917 | break; |
1918 | |
1919 | case META_GRAB_OP_CLICKING_MAXIMIZE: |
1920 | case META_GRAB_OP_CLICKING_MAXIMIZE_VERTICAL: |
1921 | case META_GRAB_OP_CLICKING_MAXIMIZE_HORIZONTAL: |
1922 | if (control == META_FRAME_CONTROL_MAXIMIZE) |
1923 | { |
1924 | /* Focus the window on the maximize */ |
1925 | meta_core_user_focus (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
1926 | frame->xwindow, |
1927 | event->time); |
1928 | |
1929 | if (op == META_GRAB_OP_CLICKING_MAXIMIZE) |
1930 | meta_core_maximize (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1931 | if (op == META_GRAB_OP_CLICKING_MAXIMIZE_VERTICAL) |
1932 | meta_core_toggle_maximize_vertically (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1933 | if (op == META_GRAB_OP_CLICKING_MAXIMIZE_HORIZONTAL) |
1934 | meta_core_toggle_maximize_horizontally (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1935 | } |
1936 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
1937 | break; |
1938 | |
1939 | case META_GRAB_OP_CLICKING_UNMAXIMIZE: |
1940 | case META_GRAB_OP_CLICKING_UNMAXIMIZE_VERTICAL: |
1941 | case META_GRAB_OP_CLICKING_UNMAXIMIZE_HORIZONTAL: |
1942 | if (control == META_FRAME_CONTROL_UNMAXIMIZE) { |
1943 | if (op == META_GRAB_OP_CLICKING_UNMAXIMIZE) |
1944 | meta_core_unmaximize (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1945 | if (op == META_GRAB_OP_CLICKING_UNMAXIMIZE_VERTICAL) |
1946 | meta_core_toggle_maximize_vertically (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1947 | if (op == META_GRAB_OP_CLICKING_UNMAXIMIZE_HORIZONTAL) |
1948 | meta_core_toggle_maximize_horizontally (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1949 | } |
1950 | |
1951 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
1952 | break; |
1953 | |
1954 | case META_GRAB_OP_CLICKING_DELETE: |
1955 | if (control == META_FRAME_CONTROL_DELETE) |
1956 | meta_core_delete (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, event->time); |
1957 | |
1958 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
1959 | break; |
1960 | |
1961 | case META_GRAB_OP_CLICKING_MENU: |
1962 | case META_GRAB_OP_CLICKING_APPMENU: |
1963 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
1964 | break; |
1965 | |
1966 | case META_GRAB_OP_CLICKING_SHADE: |
1967 | if (control == META_FRAME_CONTROL_SHADE) |
1968 | meta_core_shade (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, event->time); |
1969 | |
1970 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
1971 | break; |
1972 | |
1973 | case META_GRAB_OP_CLICKING_UNSHADE: |
1974 | if (control == META_FRAME_CONTROL_UNSHADE) |
1975 | meta_core_unshade (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, event->time); |
1976 | |
1977 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
1978 | break; |
1979 | |
1980 | case META_GRAB_OP_CLICKING_ABOVE: |
1981 | if (control == META_FRAME_CONTROL_ABOVE) |
1982 | meta_core_make_above (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1983 | |
1984 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
1985 | break; |
1986 | |
1987 | case META_GRAB_OP_CLICKING_UNABOVE: |
1988 | if (control == META_FRAME_CONTROL_UNABOVE) |
1989 | meta_core_unmake_above (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1990 | |
1991 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
1992 | break; |
1993 | |
1994 | case META_GRAB_OP_CLICKING_STICK: |
1995 | if (control == META_FRAME_CONTROL_STICK) |
1996 | meta_core_stick (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
1997 | |
1998 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
1999 | break; |
2000 | |
2001 | case META_GRAB_OP_CLICKING_UNSTICK: |
2002 | if (control == META_FRAME_CONTROL_UNSTICK) |
2003 | meta_core_unstick (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow); |
2004 | |
2005 | meta_core_end_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), event->time); |
2006 | break; |
2007 | |
2008 | default: |
2009 | break; |
2010 | } |
2011 | |
2012 | /* Update the prelit control regardless of what button the mouse |
2013 | * was released over; needed so that the new button can become |
2014 | * prelit so to let the user know that it can now be pressed. |
2015 | * :) |
2016 | */ |
2017 | meta_frames_update_prelit_control (frames, frame, control); |
2018 | } |
2019 | |
2020 | return TRUE(!(0)); |
2021 | } |
2022 | |
2023 | static void |
2024 | meta_frames_update_prelit_control (MetaFrames *frames, |
2025 | MetaUIFrame *frame, |
2026 | MetaFrameControl control) |
2027 | { |
2028 | MetaFrameControl old_control; |
2029 | MetaCursor cursor; |
2030 | |
2031 | |
2032 | meta_verbosemeta_verbose_real ("Updating prelit control from %u to %u\n", |
2033 | frame->prelit_control, control); |
2034 | |
2035 | cursor = META_CURSOR_DEFAULT; |
2036 | |
2037 | switch (control) |
2038 | { |
2039 | case META_FRAME_CONTROL_CLIENT_AREA: |
2040 | break; |
2041 | case META_FRAME_CONTROL_NONE: |
2042 | break; |
2043 | case META_FRAME_CONTROL_TITLE: |
2044 | break; |
2045 | case META_FRAME_CONTROL_DELETE: |
2046 | break; |
2047 | case META_FRAME_CONTROL_MENU: |
2048 | break; |
2049 | case META_FRAME_CONTROL_APPMENU: |
2050 | break; |
2051 | case META_FRAME_CONTROL_MINIMIZE: |
2052 | break; |
2053 | case META_FRAME_CONTROL_MAXIMIZE: |
2054 | break; |
2055 | case META_FRAME_CONTROL_UNMAXIMIZE: |
2056 | break; |
2057 | case META_FRAME_CONTROL_SHADE: |
2058 | break; |
2059 | case META_FRAME_CONTROL_UNSHADE: |
2060 | break; |
2061 | case META_FRAME_CONTROL_ABOVE: |
2062 | break; |
2063 | case META_FRAME_CONTROL_UNABOVE: |
2064 | break; |
2065 | case META_FRAME_CONTROL_STICK: |
2066 | break; |
2067 | case META_FRAME_CONTROL_UNSTICK: |
2068 | break; |
2069 | case META_FRAME_CONTROL_RESIZE_SE: |
2070 | cursor = META_CURSOR_SE_RESIZE; |
2071 | break; |
2072 | case META_FRAME_CONTROL_RESIZE_S: |
2073 | cursor = META_CURSOR_SOUTH_RESIZE; |
2074 | break; |
2075 | case META_FRAME_CONTROL_RESIZE_SW: |
2076 | cursor = META_CURSOR_SW_RESIZE; |
2077 | break; |
2078 | case META_FRAME_CONTROL_RESIZE_N: |
2079 | cursor = META_CURSOR_NORTH_RESIZE; |
2080 | break; |
2081 | case META_FRAME_CONTROL_RESIZE_NE: |
2082 | cursor = META_CURSOR_NE_RESIZE; |
2083 | break; |
2084 | case META_FRAME_CONTROL_RESIZE_NW: |
2085 | cursor = META_CURSOR_NW_RESIZE; |
2086 | break; |
2087 | case META_FRAME_CONTROL_RESIZE_W: |
2088 | cursor = META_CURSOR_WEST_RESIZE; |
2089 | break; |
2090 | case META_FRAME_CONTROL_RESIZE_E: |
2091 | cursor = META_CURSOR_EAST_RESIZE; |
2092 | break; |
2093 | } |
2094 | |
2095 | /* set/unset the prelight cursor */ |
2096 | meta_core_set_screen_cursor (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), |
2097 | frame->xwindow, |
2098 | cursor); |
2099 | |
2100 | switch (control) |
2101 | { |
2102 | case META_FRAME_CONTROL_MENU: |
2103 | case META_FRAME_CONTROL_APPMENU: |
2104 | case META_FRAME_CONTROL_MINIMIZE: |
2105 | case META_FRAME_CONTROL_MAXIMIZE: |
2106 | case META_FRAME_CONTROL_DELETE: |
2107 | case META_FRAME_CONTROL_SHADE: |
2108 | case META_FRAME_CONTROL_UNSHADE: |
2109 | case META_FRAME_CONTROL_ABOVE: |
2110 | case META_FRAME_CONTROL_UNABOVE: |
2111 | case META_FRAME_CONTROL_STICK: |
2112 | case META_FRAME_CONTROL_UNSTICK: |
2113 | case META_FRAME_CONTROL_UNMAXIMIZE: |
2114 | /* leave control set */ |
2115 | break; |
2116 | default: |
2117 | /* Only prelight buttons */ |
2118 | control = META_FRAME_CONTROL_NONE; |
2119 | break; |
2120 | } |
2121 | |
2122 | if (control == frame->prelit_control) |
2123 | return; |
2124 | |
2125 | /* Save the old control so we can unprelight it */ |
2126 | old_control = frame->prelit_control; |
2127 | |
2128 | frame->prelit_control = control; |
2129 | |
2130 | redraw_control (frames, frame, old_control); |
2131 | redraw_control (frames, frame, control); |
2132 | } |
2133 | |
2134 | static gboolean |
2135 | meta_frames_motion_notify_event (CtkWidget *widget, |
2136 | CdkEventMotion *event) |
2137 | { |
2138 | MetaUIFrame *frame; |
2139 | MetaFrames *frames; |
2140 | MetaGrabOp grab_op; |
2141 | |
2142 | frames = META_FRAMES (widget)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((meta_frames_get_type ())))))); |
2143 | |
2144 | frame = meta_frames_lookup_window (frames, CDK_WINDOW_XID (event->window)(cdk_x11_window_get_xid (event->window))); |
2145 | if (frame == NULL((void*)0)) |
2146 | return FALSE(0); |
2147 | |
2148 | clear_tip (frames); |
2149 | |
2150 | frames->last_motion_frame = frame; |
2151 | |
2152 | grab_op = meta_core_get_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ()))); |
2153 | |
2154 | switch (grab_op) |
2155 | { |
2156 | case META_GRAB_OP_CLICKING_MENU: |
2157 | case META_GRAB_OP_CLICKING_APPMENU: |
2158 | case META_GRAB_OP_CLICKING_DELETE: |
2159 | case META_GRAB_OP_CLICKING_MINIMIZE: |
2160 | case META_GRAB_OP_CLICKING_MAXIMIZE: |
2161 | case META_GRAB_OP_CLICKING_MAXIMIZE_VERTICAL: |
2162 | case META_GRAB_OP_CLICKING_MAXIMIZE_HORIZONTAL: |
2163 | case META_GRAB_OP_CLICKING_UNMAXIMIZE: |
2164 | case META_GRAB_OP_CLICKING_UNMAXIMIZE_VERTICAL: |
2165 | case META_GRAB_OP_CLICKING_UNMAXIMIZE_HORIZONTAL: |
2166 | case META_GRAB_OP_CLICKING_SHADE: |
2167 | case META_GRAB_OP_CLICKING_UNSHADE: |
2168 | case META_GRAB_OP_CLICKING_ABOVE: |
2169 | case META_GRAB_OP_CLICKING_UNABOVE: |
2170 | case META_GRAB_OP_CLICKING_STICK: |
2171 | case META_GRAB_OP_CLICKING_UNSTICK: |
2172 | { |
2173 | MetaFrameControl control; |
2174 | int x, y, scale; |
2175 | |
2176 | cdk_window_get_device_position (frame->window, event->device, |
2177 | &x, &y, NULL((void*)0)); |
2178 | scale = cdk_window_get_scale_factor (frame->window); |
2179 | x *= scale; |
2180 | y *= scale; |
2181 | |
2182 | /* Control is set to none unless it matches |
2183 | * the current grab |
2184 | */ |
2185 | control = get_control (frames, frame, x, y); |
2186 | if (! ((control == META_FRAME_CONTROL_MENU && |
2187 | grab_op == META_GRAB_OP_CLICKING_MENU) || |
2188 | (control == META_FRAME_CONTROL_APPMENU && |
2189 | grab_op == META_GRAB_OP_CLICKING_APPMENU) || |
2190 | (control == META_FRAME_CONTROL_DELETE && |
2191 | grab_op == META_GRAB_OP_CLICKING_DELETE) || |
2192 | (control == META_FRAME_CONTROL_MINIMIZE && |
2193 | grab_op == META_GRAB_OP_CLICKING_MINIMIZE) || |
2194 | ((control == META_FRAME_CONTROL_MAXIMIZE || |
2195 | control == META_FRAME_CONTROL_UNMAXIMIZE) && |
2196 | (grab_op == META_GRAB_OP_CLICKING_MAXIMIZE || |
2197 | grab_op == META_GRAB_OP_CLICKING_MAXIMIZE_VERTICAL || |
2198 | grab_op == META_GRAB_OP_CLICKING_MAXIMIZE_HORIZONTAL || |
2199 | grab_op == META_GRAB_OP_CLICKING_UNMAXIMIZE || |
2200 | grab_op == META_GRAB_OP_CLICKING_UNMAXIMIZE_VERTICAL || |
2201 | grab_op == META_GRAB_OP_CLICKING_UNMAXIMIZE_HORIZONTAL)) || |
2202 | (control == META_FRAME_CONTROL_SHADE && |
2203 | grab_op == META_GRAB_OP_CLICKING_SHADE) || |
2204 | (control == META_FRAME_CONTROL_UNSHADE && |
2205 | grab_op == META_GRAB_OP_CLICKING_UNSHADE) || |
2206 | (control == META_FRAME_CONTROL_ABOVE && |
2207 | grab_op == META_GRAB_OP_CLICKING_ABOVE) || |
2208 | (control == META_FRAME_CONTROL_UNABOVE && |
2209 | grab_op == META_GRAB_OP_CLICKING_UNABOVE) || |
2210 | (control == META_FRAME_CONTROL_STICK && |
2211 | grab_op == META_GRAB_OP_CLICKING_STICK) || |
2212 | (control == META_FRAME_CONTROL_UNSTICK && |
2213 | grab_op == META_GRAB_OP_CLICKING_UNSTICK))) |
2214 | control = META_FRAME_CONTROL_NONE; |
2215 | |
2216 | /* Update prelit control and cursor */ |
2217 | meta_frames_update_prelit_control (frames, frame, control); |
2218 | |
2219 | /* No tooltip while in the process of clicking */ |
2220 | } |
2221 | break; |
2222 | case META_GRAB_OP_NONE: |
2223 | { |
2224 | MetaFrameControl control; |
2225 | int x, y, scale; |
2226 | |
2227 | cdk_window_get_device_position (frame->window, event->device, |
2228 | &x, &y, NULL((void*)0)); |
2229 | scale = cdk_window_get_scale_factor (frame->window); |
2230 | x *= scale; |
2231 | y *= scale; |
2232 | |
2233 | control = get_control (frames, frame, x, y); |
2234 | |
2235 | /* Update prelit control and cursor */ |
2236 | meta_frames_update_prelit_control (frames, frame, control); |
2237 | |
2238 | queue_tip (frames); |
2239 | } |
2240 | break; |
2241 | |
2242 | default: |
2243 | break; |
2244 | } |
2245 | |
2246 | return TRUE(!(0)); |
2247 | } |
2248 | |
2249 | static gboolean |
2250 | meta_frames_destroy_event (CtkWidget *widget, |
2251 | CdkEventAny *event) |
2252 | { |
2253 | MetaUIFrame *frame; |
2254 | MetaFrames *frames; |
2255 | |
2256 | frames = META_FRAMES (widget)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((meta_frames_get_type ())))))); |
2257 | |
2258 | frame = meta_frames_lookup_window (frames, CDK_WINDOW_XID (event->window)(cdk_x11_window_get_xid (event->window))); |
2259 | if (frame == NULL((void*)0)) |
2260 | return FALSE(0); |
2261 | |
2262 | return TRUE(!(0)); |
2263 | } |
2264 | |
2265 | /* Returns a pixmap with a piece of the windows frame painted on it. |
2266 | */ |
2267 | static cairo_surface_t * |
2268 | generate_pixmap (MetaFrames *frames, |
2269 | MetaUIFrame *frame, |
2270 | cairo_rectangle_int_t *rect) |
2271 | { |
2272 | cairo_surface_t *result; |
2273 | cairo_t *cr; |
2274 | |
2275 | /* do not create a pixmap for nonexisting areas */ |
2276 | if (rect->width <= 0 || rect->height <= 0) |
2277 | return NULL((void*)0); |
2278 | |
2279 | result = cdk_window_create_similar_surface (frame->window, |
2280 | CAIRO_CONTENT_COLOR_ALPHA, |
2281 | rect->width, rect->height); |
2282 | |
2283 | cr = cairo_create (result); |
2284 | cairo_translate (cr, -rect->x, -rect->y); |
2285 | |
2286 | cairo_paint (cr); |
2287 | |
2288 | meta_frames_paint_to_drawable (frames, frame, cr); |
2289 | |
2290 | cairo_destroy (cr); |
2291 | |
2292 | return result; |
2293 | } |
2294 | |
2295 | static void |
2296 | populate_cache (MetaFrames *frames, |
2297 | MetaUIFrame *frame) |
2298 | { |
2299 | MetaFrameBorders borders; |
2300 | int width, height; |
2301 | int frame_width, frame_height, screen_width, screen_height; |
2302 | CachedPixels *pixels; |
2303 | MetaFrameType frame_type; |
2304 | MetaFrameFlags frame_flags; |
2305 | int i; |
2306 | |
2307 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
2308 | META_CORE_GET_FRAME_WIDTH, &frame_width, |
2309 | META_CORE_GET_FRAME_HEIGHT, &frame_height, |
2310 | META_CORE_GET_SCREEN_WIDTH, &screen_width, |
2311 | META_CORE_GET_SCREEN_HEIGHT, &screen_height, |
2312 | META_CORE_GET_CLIENT_WIDTH, &width, |
2313 | META_CORE_GET_CLIENT_HEIGHT, &height, |
2314 | META_CORE_GET_FRAME_TYPE, &frame_type, |
2315 | META_CORE_GET_FRAME_FLAGS, &frame_flags, |
2316 | META_CORE_GET_END); |
2317 | |
2318 | /* don't cache extremely large windows */ |
2319 | if (frame_width > 2 * screen_width || |
2320 | frame_height > 2 * screen_height) |
2321 | { |
2322 | return; |
2323 | } |
2324 | |
2325 | meta_theme_get_frame_borders (meta_theme_get_current (), |
2326 | frame_type, |
2327 | frame->text_height, |
2328 | frame_flags, |
2329 | &borders); |
2330 | |
2331 | pixels = get_cache (frames, frame); |
2332 | |
2333 | /* Setup the rectangles for the four visible frame borders. First top, then |
2334 | * left, right and bottom. Top and bottom extend to the invisible borders |
2335 | * while left and right snugly fit in between: |
2336 | * ----- |
2337 | * | | |
2338 | * ----- |
2339 | */ |
2340 | |
2341 | /* width and height refer to the client window's |
2342 | * size without any border added. */ |
2343 | |
2344 | /* top */ |
2345 | pixels->piece[0].rect.x = 0; |
2346 | pixels->piece[0].rect.y = 0; |
2347 | pixels->piece[0].rect.width = width + borders.total.left + borders.total.right; |
2348 | pixels->piece[0].rect.height = borders.total.top; |
2349 | |
2350 | /* left */ |
2351 | pixels->piece[1].rect.x = 0; |
2352 | pixels->piece[1].rect.y = borders.total.top; |
2353 | pixels->piece[1].rect.width = borders.total.left; |
2354 | pixels->piece[1].rect.height = height; |
2355 | |
2356 | /* right */ |
2357 | pixels->piece[2].rect.x = borders.total.left + width; |
2358 | pixels->piece[2].rect.y = borders.total.top; |
2359 | pixels->piece[2].rect.width = borders.total.right; |
2360 | pixels->piece[2].rect.height = height; |
2361 | |
2362 | /* bottom */ |
2363 | pixels->piece[3].rect.x = 0; |
2364 | pixels->piece[3].rect.y = borders.total.top + height; |
2365 | pixels->piece[3].rect.width = width + borders.total.left + borders.total.right; |
2366 | pixels->piece[3].rect.height = borders.total.bottom; |
2367 | |
2368 | for (i = 0; i < 4; i++) |
2369 | { |
2370 | CachedFramePiece *piece = &pixels->piece[i]; |
2371 | if (!piece->pixmap) |
2372 | piece->pixmap = generate_pixmap (frames, frame, &piece->rect); |
2373 | } |
2374 | |
2375 | if (frames->invalidate_cache_timeout_id) |
2376 | g_source_remove (frames->invalidate_cache_timeout_id); |
2377 | |
2378 | frames->invalidate_cache_timeout_id = g_timeout_add (1000, invalidate_cache_timeout, frames); |
2379 | |
2380 | if (!g_list_find (frames->invalidate_frames, frame)) |
2381 | frames->invalidate_frames = |
2382 | g_list_prepend (frames->invalidate_frames, frame); |
2383 | } |
2384 | |
2385 | static void |
2386 | clip_to_screen (cairo_region_t *region, MetaUIFrame *frame) |
2387 | { |
2388 | CdkRectangle frame_area; |
2389 | CdkRectangle screen_area = { 0, 0, 0, 0 }; |
2390 | cairo_region_t *tmp_region; |
2391 | |
2392 | /* Chop off stuff outside the screen; this optimization |
2393 | * is crucial to handle huge client windows, |
2394 | * like "xterm -geometry 1000x1000" |
2395 | */ |
2396 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
2397 | META_CORE_GET_FRAME_X, &frame_area.x, |
2398 | META_CORE_GET_FRAME_Y, &frame_area.y, |
2399 | META_CORE_GET_FRAME_WIDTH, &frame_area.width, |
2400 | META_CORE_GET_FRAME_HEIGHT, &frame_area.height, |
2401 | META_CORE_GET_SCREEN_WIDTH, &screen_area.width, |
2402 | META_CORE_GET_SCREEN_HEIGHT, &screen_area.height, |
2403 | META_CORE_GET_END); |
2404 | |
2405 | cairo_region_translate (region, frame_area.x, frame_area.y); |
2406 | |
2407 | tmp_region = cairo_region_create_rectangle (&frame_area); |
2408 | cairo_region_intersect (region, tmp_region); |
2409 | cairo_region_destroy (tmp_region); |
2410 | |
2411 | cairo_region_translate (region, - frame_area.x, - frame_area.y); |
2412 | } |
2413 | |
2414 | static void |
2415 | subtract_client_area (cairo_region_t *region, |
2416 | MetaUIFrame *frame) |
2417 | { |
2418 | cairo_rectangle_int_t area; |
2419 | MetaFrameFlags flags; |
2420 | MetaFrameType type; |
2421 | MetaFrameBorders borders; |
2422 | cairo_region_t *tmp_region; |
2423 | Display *display; |
2424 | gint scale; |
2425 | |
2426 | display = CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())); |
2427 | scale = cdk_window_get_scale_factor (frame->window); |
2428 | |
2429 | meta_core_get (display, frame->xwindow, |
2430 | META_CORE_GET_FRAME_FLAGS, &flags, |
2431 | META_CORE_GET_FRAME_TYPE, &type, |
2432 | META_CORE_GET_CLIENT_WIDTH, &area.width, |
2433 | META_CORE_GET_CLIENT_HEIGHT, &area.height, |
2434 | META_CORE_GET_END); |
2435 | meta_theme_get_frame_borders (meta_theme_get_current (), |
2436 | type, frame->text_height, flags, |
2437 | &borders); |
2438 | |
2439 | area.width /= scale; |
2440 | area.height /= scale; |
2441 | area.x = borders.total.left / scale; |
2442 | area.y = borders.total.top / scale; |
2443 | |
2444 | tmp_region = cairo_region_create_rectangle (&area); |
2445 | cairo_region_subtract (region, tmp_region); |
2446 | cairo_region_destroy (tmp_region); |
2447 | } |
2448 | |
2449 | static void |
2450 | cached_pixels_draw (CachedPixels *pixels, |
2451 | cairo_t *cr, |
2452 | cairo_region_t *region) |
2453 | { |
2454 | cairo_region_t *region_piece; |
2455 | int i; |
2456 | |
2457 | for (i = 0; i < 4; i++) |
2458 | { |
2459 | CachedFramePiece *piece; |
2460 | piece = &pixels->piece[i]; |
2461 | |
2462 | if (piece->pixmap) |
2463 | { |
2464 | cairo_set_source_surface (cr, piece->pixmap, |
2465 | piece->rect.x, piece->rect.y); |
2466 | cairo_paint (cr); |
2467 | |
2468 | region_piece = cairo_region_create_rectangle (&piece->rect); |
2469 | cairo_region_subtract (region, region_piece); |
2470 | cairo_region_destroy (region_piece); |
2471 | } |
2472 | } |
2473 | } |
2474 | |
2475 | static MetaUIFrame * |
2476 | find_frame_to_draw (MetaFrames *frames, |
2477 | cairo_t *cr) |
2478 | { |
2479 | GHashTableIter iter; |
2480 | MetaUIFrame *frame; |
2481 | |
2482 | g_hash_table_iter_init (&iter, frames->frames); |
2483 | while (g_hash_table_iter_next (&iter, NULL((void*)0), (gpointer *) &frame)) |
2484 | if (ctk_cairo_should_draw_window (cr, frame->window)) |
2485 | return frame; |
2486 | |
2487 | return NULL((void*)0); |
2488 | } |
2489 | |
2490 | static gboolean |
2491 | meta_frames_draw (CtkWidget *widget, |
2492 | cairo_t *cr) |
2493 | { |
2494 | MetaUIFrame *frame; |
2495 | MetaFrames *frames; |
2496 | CachedPixels *pixels; |
2497 | cairo_region_t *region; |
2498 | cairo_rectangle_int_t clip; |
2499 | int i, n_areas; |
2500 | |
2501 | frames = META_FRAMES (widget)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((meta_frames_get_type ())))))); |
2502 | cdk_cairo_get_clip_rectangle (cr, &clip); |
2503 | |
2504 | frame = find_frame_to_draw (frames, cr); |
2505 | |
2506 | if (frame == NULL((void*)0)) |
2507 | return FALSE(0); |
2508 | |
2509 | if (frames->expose_delay_count > 0) |
2510 | { |
2511 | /* Redraw this entire frame later */ |
2512 | frame->expose_delayed = TRUE(!(0)); |
2513 | return TRUE(!(0)); |
2514 | } |
2515 | |
2516 | populate_cache (frames, frame); |
2517 | |
2518 | region = cairo_region_create_rectangle (&clip); |
2519 | |
2520 | pixels = get_cache (frames, frame); |
2521 | |
2522 | cached_pixels_draw (pixels, cr, region); |
2523 | |
2524 | clip_to_screen (region, frame); |
2525 | subtract_client_area (region, frame); |
2526 | |
2527 | n_areas = cairo_region_num_rectangles (region); |
2528 | |
2529 | for (i = 0; i < n_areas; i++) |
2530 | { |
2531 | cairo_rectangle_int_t area; |
2532 | |
2533 | cairo_region_get_rectangle (region, i, &area); |
2534 | |
2535 | cairo_save (cr); |
2536 | |
2537 | cairo_rectangle (cr, area.x, area.y, area.width, area.height); |
2538 | cairo_clip (cr); |
2539 | |
2540 | cairo_push_group (cr); |
2541 | |
2542 | meta_frames_paint_to_drawable (frames, frame, cr); |
2543 | |
2544 | cairo_pop_group_to_source (cr); |
2545 | cairo_paint (cr); |
2546 | |
2547 | cairo_restore (cr); |
2548 | } |
2549 | |
2550 | cairo_region_destroy (region); |
2551 | |
2552 | return TRUE(!(0)); |
2553 | } |
2554 | |
2555 | /* How far off the screen edge the window decorations should |
2556 | * be drawn. Used only in meta_frames_paint_to_drawable, below. |
2557 | */ |
2558 | #define DECORATING_BORDER100 100 |
2559 | |
2560 | static void |
2561 | meta_frames_paint_to_drawable (MetaFrames *frames, |
2562 | MetaUIFrame *frame, |
2563 | cairo_t *cr) |
2564 | { |
2565 | MetaFrameFlags flags; |
2566 | MetaFrameType type; |
2567 | GdkPixbuf *mini_icon; |
2568 | GdkPixbuf *icon; |
2569 | int w, h, scale; |
2570 | MetaButtonState button_states[META_BUTTON_TYPE_LAST]; |
2571 | Window grab_frame; |
2572 | int i; |
2573 | MetaButtonLayout button_layout; |
2574 | MetaGrabOp grab_op; |
2575 | |
2576 | for (i = 0; i < META_BUTTON_TYPE_LAST; i++) |
2577 | button_states[i] = META_BUTTON_STATE_NORMAL; |
2578 | |
2579 | grab_frame = meta_core_get_grab_frame (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ()))); |
2580 | grab_op = meta_core_get_grab_op (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ()))); |
2581 | if (grab_frame != frame->xwindow) |
2582 | grab_op = META_GRAB_OP_NONE; |
2583 | |
2584 | /* Set prelight state */ |
2585 | switch (frame->prelit_control) |
2586 | { |
2587 | case META_FRAME_CONTROL_MENU: |
2588 | if (grab_op == META_GRAB_OP_CLICKING_MENU) |
2589 | button_states[META_BUTTON_TYPE_MENU] = META_BUTTON_STATE_PRESSED; |
2590 | else |
2591 | button_states[META_BUTTON_TYPE_MENU] = META_BUTTON_STATE_PRELIGHT; |
2592 | break; |
2593 | case META_FRAME_CONTROL_APPMENU: |
2594 | if (grab_op == META_GRAB_OP_CLICKING_MENU) |
2595 | button_states[META_BUTTON_TYPE_APPMENU] = META_BUTTON_STATE_PRESSED; |
2596 | else |
2597 | button_states[META_BUTTON_TYPE_APPMENU] = META_BUTTON_STATE_PRELIGHT; |
2598 | break; |
2599 | case META_FRAME_CONTROL_MINIMIZE: |
2600 | if (grab_op == META_GRAB_OP_CLICKING_MINIMIZE) |
2601 | button_states[META_BUTTON_TYPE_MINIMIZE] = META_BUTTON_STATE_PRESSED; |
2602 | else |
2603 | button_states[META_BUTTON_TYPE_MINIMIZE] = META_BUTTON_STATE_PRELIGHT; |
2604 | break; |
2605 | case META_FRAME_CONTROL_MAXIMIZE: |
2606 | if (grab_op == META_GRAB_OP_CLICKING_MAXIMIZE || grab_op == META_GRAB_OP_CLICKING_MAXIMIZE_VERTICAL || |
2607 | grab_op == META_GRAB_OP_CLICKING_MAXIMIZE_HORIZONTAL) |
2608 | button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRESSED; |
2609 | else |
2610 | button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRELIGHT; |
2611 | break; |
2612 | case META_FRAME_CONTROL_UNMAXIMIZE: |
2613 | if (grab_op == META_GRAB_OP_CLICKING_UNMAXIMIZE || grab_op == META_GRAB_OP_CLICKING_UNMAXIMIZE_VERTICAL || |
2614 | grab_op == META_GRAB_OP_CLICKING_UNMAXIMIZE_HORIZONTAL) |
2615 | button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRESSED; |
2616 | else |
2617 | button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRELIGHT; |
2618 | break; |
2619 | case META_FRAME_CONTROL_SHADE: |
2620 | if (grab_op == META_GRAB_OP_CLICKING_SHADE) |
2621 | button_states[META_BUTTON_TYPE_SHADE] = META_BUTTON_STATE_PRESSED; |
2622 | else |
2623 | button_states[META_BUTTON_TYPE_SHADE] = META_BUTTON_STATE_PRELIGHT; |
2624 | break; |
2625 | case META_FRAME_CONTROL_UNSHADE: |
2626 | if (grab_op == META_GRAB_OP_CLICKING_UNSHADE) |
2627 | button_states[META_BUTTON_TYPE_UNSHADE] = META_BUTTON_STATE_PRESSED; |
2628 | else |
2629 | button_states[META_BUTTON_TYPE_UNSHADE] = META_BUTTON_STATE_PRELIGHT; |
2630 | break; |
2631 | case META_FRAME_CONTROL_ABOVE: |
2632 | if (grab_op == META_GRAB_OP_CLICKING_ABOVE) |
2633 | button_states[META_BUTTON_TYPE_ABOVE] = META_BUTTON_STATE_PRESSED; |
2634 | else |
2635 | button_states[META_BUTTON_TYPE_ABOVE] = META_BUTTON_STATE_PRELIGHT; |
2636 | break; |
2637 | case META_FRAME_CONTROL_UNABOVE: |
2638 | if (grab_op == META_GRAB_OP_CLICKING_UNABOVE) |
2639 | button_states[META_BUTTON_TYPE_UNABOVE] = META_BUTTON_STATE_PRESSED; |
2640 | else |
2641 | button_states[META_BUTTON_TYPE_UNABOVE] = META_BUTTON_STATE_PRELIGHT; |
2642 | break; |
2643 | case META_FRAME_CONTROL_STICK: |
2644 | if (grab_op == META_GRAB_OP_CLICKING_STICK) |
2645 | button_states[META_BUTTON_TYPE_STICK] = META_BUTTON_STATE_PRESSED; |
2646 | else |
2647 | button_states[META_BUTTON_TYPE_STICK] = META_BUTTON_STATE_PRELIGHT; |
2648 | break; |
2649 | case META_FRAME_CONTROL_UNSTICK: |
2650 | if (grab_op == META_GRAB_OP_CLICKING_UNSTICK) |
2651 | button_states[META_BUTTON_TYPE_UNSTICK] = META_BUTTON_STATE_PRESSED; |
2652 | else |
2653 | button_states[META_BUTTON_TYPE_UNSTICK] = META_BUTTON_STATE_PRELIGHT; |
2654 | break; |
2655 | case META_FRAME_CONTROL_DELETE: |
2656 | if (grab_op == META_GRAB_OP_CLICKING_DELETE) |
2657 | button_states[META_BUTTON_TYPE_CLOSE] = META_BUTTON_STATE_PRESSED; |
2658 | else |
2659 | button_states[META_BUTTON_TYPE_CLOSE] = META_BUTTON_STATE_PRELIGHT; |
2660 | break; |
2661 | default: |
2662 | break; |
2663 | } |
2664 | |
2665 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
2666 | META_CORE_GET_FRAME_FLAGS, &flags, |
2667 | META_CORE_GET_FRAME_TYPE, &type, |
2668 | META_CORE_GET_MINI_ICON, &mini_icon, |
2669 | META_CORE_GET_ICON, &icon, |
2670 | META_CORE_GET_CLIENT_WIDTH, &w, |
2671 | META_CORE_GET_CLIENT_HEIGHT, &h, |
2672 | META_CORE_GET_END); |
2673 | |
2674 | meta_frames_ensure_layout (frames, frame); |
2675 | |
2676 | meta_prefs_get_button_layout (&button_layout); |
2677 | |
2678 | scale = cdk_window_get_scale_factor (frame->window); |
2679 | meta_theme_draw_frame (meta_theme_get_current (), |
2680 | frame->style, |
2681 | cr, |
2682 | type, |
2683 | flags, |
2684 | w / scale, |
2685 | h / scale, |
2686 | frame->text_layout, |
2687 | frame->text_height, |
2688 | &button_layout, |
2689 | button_states, |
2690 | mini_icon, |
2691 | icon); |
2692 | } |
2693 | |
2694 | static gboolean |
2695 | meta_frames_enter_notify_event (CtkWidget *widget, |
2696 | CdkEventCrossing *event) |
2697 | { |
2698 | MetaUIFrame *frame; |
2699 | MetaFrames *frames; |
2700 | MetaFrameControl control; |
2701 | |
2702 | frames = META_FRAMES (widget)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((meta_frames_get_type ())))))); |
2703 | |
2704 | frame = meta_frames_lookup_window (frames, CDK_WINDOW_XID (event->window)(cdk_x11_window_get_xid (event->window))); |
2705 | if (frame == NULL((void*)0)) |
2706 | return FALSE(0); |
2707 | |
2708 | control = get_control (frames, frame, event->x, event->y); |
2709 | meta_frames_update_prelit_control (frames, frame, control); |
2710 | |
2711 | return TRUE(!(0)); |
2712 | } |
2713 | |
2714 | static gboolean |
2715 | meta_frames_leave_notify_event (CtkWidget *widget, |
2716 | CdkEventCrossing *event) |
2717 | { |
2718 | MetaUIFrame *frame; |
2719 | MetaFrames *frames; |
2720 | |
2721 | frames = META_FRAMES (widget)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((meta_frames_get_type ())))))); |
2722 | |
2723 | frame = meta_frames_lookup_window (frames, CDK_WINDOW_XID (event->window)(cdk_x11_window_get_xid (event->window))); |
2724 | if (frame == NULL((void*)0)) |
2725 | return FALSE(0); |
2726 | |
2727 | meta_frames_update_prelit_control (frames, frame, META_FRAME_CONTROL_NONE); |
2728 | |
2729 | clear_tip (frames); |
2730 | |
2731 | return TRUE(!(0)); |
2732 | } |
2733 | |
2734 | static CdkRectangle* |
2735 | control_rect (MetaFrameControl control, |
2736 | MetaFrameGeometry *fgeom) |
2737 | { |
2738 | CdkRectangle *rect; |
2739 | |
2740 | rect = NULL((void*)0); |
2741 | switch (control) |
2742 | { |
2743 | case META_FRAME_CONTROL_TITLE: |
2744 | rect = &fgeom->title_rect; |
2745 | break; |
2746 | case META_FRAME_CONTROL_DELETE: |
2747 | rect = &fgeom->close_rect.visible; |
2748 | break; |
2749 | case META_FRAME_CONTROL_MENU: |
2750 | rect = &fgeom->menu_rect.visible; |
2751 | break; |
2752 | case META_FRAME_CONTROL_APPMENU: |
2753 | rect = &fgeom->appmenu_rect.visible; |
2754 | break; |
2755 | case META_FRAME_CONTROL_MINIMIZE: |
2756 | rect = &fgeom->min_rect.visible; |
2757 | break; |
2758 | case META_FRAME_CONTROL_MAXIMIZE: |
2759 | case META_FRAME_CONTROL_UNMAXIMIZE: |
2760 | rect = &fgeom->max_rect.visible; |
2761 | break; |
2762 | case META_FRAME_CONTROL_SHADE: |
2763 | rect = &fgeom->shade_rect.visible; |
2764 | break; |
2765 | case META_FRAME_CONTROL_UNSHADE: |
2766 | rect = &fgeom->unshade_rect.visible; |
2767 | break; |
2768 | case META_FRAME_CONTROL_ABOVE: |
2769 | rect = &fgeom->above_rect.visible; |
2770 | break; |
2771 | case META_FRAME_CONTROL_UNABOVE: |
2772 | rect = &fgeom->unabove_rect.visible; |
2773 | break; |
2774 | case META_FRAME_CONTROL_STICK: |
2775 | rect = &fgeom->stick_rect.visible; |
2776 | break; |
2777 | case META_FRAME_CONTROL_UNSTICK: |
2778 | rect = &fgeom->unstick_rect.visible; |
2779 | break; |
2780 | case META_FRAME_CONTROL_RESIZE_SE: |
2781 | break; |
2782 | case META_FRAME_CONTROL_RESIZE_S: |
2783 | break; |
2784 | case META_FRAME_CONTROL_RESIZE_SW: |
2785 | break; |
2786 | case META_FRAME_CONTROL_RESIZE_N: |
2787 | break; |
2788 | case META_FRAME_CONTROL_RESIZE_NE: |
2789 | break; |
2790 | case META_FRAME_CONTROL_RESIZE_NW: |
2791 | break; |
2792 | case META_FRAME_CONTROL_RESIZE_W: |
2793 | break; |
2794 | case META_FRAME_CONTROL_RESIZE_E: |
2795 | break; |
2796 | case META_FRAME_CONTROL_NONE: |
2797 | break; |
2798 | case META_FRAME_CONTROL_CLIENT_AREA: |
2799 | break; |
2800 | } |
2801 | |
2802 | return rect; |
2803 | } |
2804 | |
2805 | #define RESIZE_EXTENDS15 15 |
2806 | #define TOP_RESIZE_HEIGHT4 4 |
2807 | static MetaFrameControl |
2808 | get_control (MetaFrames *frames, |
2809 | MetaUIFrame *frame, |
2810 | int x, int y) |
2811 | { |
2812 | MetaFrameGeometry fgeom; |
2813 | MetaFrameFlags flags; |
2814 | gboolean has_vert, has_horiz; |
2815 | CdkRectangle client; |
2816 | gint scale; |
2817 | |
2818 | scale = cdk_window_get_scale_factor (frame->window); |
2819 | x /= scale; |
2820 | y /= scale; |
2821 | |
2822 | meta_frames_calc_geometry (frames, frame, &fgeom); |
2823 | get_client_rect (&fgeom, fgeom.width, fgeom.height, &client); |
2824 | |
2825 | if (POINT_IN_RECT (x, y, client)((x) >= (client).x && (x) < ((client).x + (client ).width) && (y) >= (client).y && (y) < ( (client).y + (client).height))) |
2826 | return META_FRAME_CONTROL_CLIENT_AREA; |
2827 | |
2828 | if (POINT_IN_RECT (x, y, fgeom.close_rect.clickable)((x) >= (fgeom.close_rect.clickable).x && (x) < ((fgeom.close_rect.clickable).x + (fgeom.close_rect.clickable ).width) && (y) >= (fgeom.close_rect.clickable).y && (y) < ((fgeom.close_rect.clickable).y + (fgeom.close_rect .clickable).height))) |
2829 | return META_FRAME_CONTROL_DELETE; |
2830 | |
2831 | if (POINT_IN_RECT (x, y, fgeom.min_rect.clickable)((x) >= (fgeom.min_rect.clickable).x && (x) < ( (fgeom.min_rect.clickable).x + (fgeom.min_rect.clickable).width ) && (y) >= (fgeom.min_rect.clickable).y && (y) < ((fgeom.min_rect.clickable).y + (fgeom.min_rect.clickable ).height))) |
2832 | return META_FRAME_CONTROL_MINIMIZE; |
2833 | |
2834 | if (POINT_IN_RECT (x, y, fgeom.menu_rect.clickable)((x) >= (fgeom.menu_rect.clickable).x && (x) < ( (fgeom.menu_rect.clickable).x + (fgeom.menu_rect.clickable).width ) && (y) >= (fgeom.menu_rect.clickable).y && (y) < ((fgeom.menu_rect.clickable).y + (fgeom.menu_rect.clickable ).height))) |
2835 | return META_FRAME_CONTROL_MENU; |
2836 | |
2837 | if (POINT_IN_RECT (x, y, fgeom.appmenu_rect.clickable)((x) >= (fgeom.appmenu_rect.clickable).x && (x) < ((fgeom.appmenu_rect.clickable).x + (fgeom.appmenu_rect.clickable ).width) && (y) >= (fgeom.appmenu_rect.clickable). y && (y) < ((fgeom.appmenu_rect.clickable).y + (fgeom .appmenu_rect.clickable).height))) |
2838 | return META_FRAME_CONTROL_APPMENU; |
2839 | |
2840 | meta_core_get (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), frame->xwindow, |
2841 | META_CORE_GET_FRAME_FLAGS, &flags, |
2842 | META_CORE_GET_END); |
2843 | |
2844 | has_vert = (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) != 0; |
2845 | has_horiz = (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) != 0; |
2846 | |
2847 | if (POINT_IN_RECT (x, y, fgeom.title_rect)((x) >= (fgeom.title_rect).x && (x) < ((fgeom.title_rect ).x + (fgeom.title_rect).width) && (y) >= (fgeom.title_rect ).y && (y) < ((fgeom.title_rect).y + (fgeom.title_rect ).height))) |
2848 | { |
2849 | if (has_vert && y <= TOP_RESIZE_HEIGHT4 * scale) |
2850 | return META_FRAME_CONTROL_RESIZE_N; |
2851 | else |
2852 | return META_FRAME_CONTROL_TITLE; |
2853 | } |
2854 | |
2855 | if (POINT_IN_RECT (x, y, fgeom.max_rect.clickable)((x) >= (fgeom.max_rect.clickable).x && (x) < ( (fgeom.max_rect.clickable).x + (fgeom.max_rect.clickable).width ) && (y) >= (fgeom.max_rect.clickable).y && (y) < ((fgeom.max_rect.clickable).y + (fgeom.max_rect.clickable ).height))) |
2856 | { |
2857 | if (flags & META_FRAME_MAXIMIZED) |
2858 | return META_FRAME_CONTROL_UNMAXIMIZE; |
2859 | else |
2860 | return META_FRAME_CONTROL_MAXIMIZE; |
2861 | } |
2862 | |
2863 | if (POINT_IN_RECT (x, y, fgeom.shade_rect.clickable)((x) >= (fgeom.shade_rect.clickable).x && (x) < ((fgeom.shade_rect.clickable).x + (fgeom.shade_rect.clickable ).width) && (y) >= (fgeom.shade_rect.clickable).y && (y) < ((fgeom.shade_rect.clickable).y + (fgeom.shade_rect .clickable).height))) |
2864 | { |
2865 | return META_FRAME_CONTROL_SHADE; |
2866 | } |
2867 | |
2868 | if (POINT_IN_RECT (x, y, fgeom.unshade_rect.clickable)((x) >= (fgeom.unshade_rect.clickable).x && (x) < ((fgeom.unshade_rect.clickable).x + (fgeom.unshade_rect.clickable ).width) && (y) >= (fgeom.unshade_rect.clickable). y && (y) < ((fgeom.unshade_rect.clickable).y + (fgeom .unshade_rect.clickable).height))) |
2869 | { |
2870 | return META_FRAME_CONTROL_UNSHADE; |
2871 | } |
2872 | |
2873 | if (POINT_IN_RECT (x, y, fgeom.above_rect.clickable)((x) >= (fgeom.above_rect.clickable).x && (x) < ((fgeom.above_rect.clickable).x + (fgeom.above_rect.clickable ).width) && (y) >= (fgeom.above_rect.clickable).y && (y) < ((fgeom.above_rect.clickable).y + (fgeom.above_rect .clickable).height))) |
2874 | { |
2875 | return META_FRAME_CONTROL_ABOVE; |
2876 | } |
2877 | |
2878 | if (POINT_IN_RECT (x, y, fgeom.unabove_rect.clickable)((x) >= (fgeom.unabove_rect.clickable).x && (x) < ((fgeom.unabove_rect.clickable).x + (fgeom.unabove_rect.clickable ).width) && (y) >= (fgeom.unabove_rect.clickable). y && (y) < ((fgeom.unabove_rect.clickable).y + (fgeom .unabove_rect.clickable).height))) |
2879 | { |
2880 | return META_FRAME_CONTROL_UNABOVE; |
2881 | } |
2882 | |
2883 | if (POINT_IN_RECT (x, y, fgeom.stick_rect.clickable)((x) >= (fgeom.stick_rect.clickable).x && (x) < ((fgeom.stick_rect.clickable).x + (fgeom.stick_rect.clickable ).width) && (y) >= (fgeom.stick_rect.clickable).y && (y) < ((fgeom.stick_rect.clickable).y + (fgeom.stick_rect .clickable).height))) |
2884 | { |
2885 | return META_FRAME_CONTROL_STICK; |
2886 | } |
2887 | |
2888 | if (POINT_IN_RECT (x, y, fgeom.unstick_rect.clickable)((x) >= (fgeom.unstick_rect.clickable).x && (x) < ((fgeom.unstick_rect.clickable).x + (fgeom.unstick_rect.clickable ).width) && (y) >= (fgeom.unstick_rect.clickable). y && (y) < ((fgeom.unstick_rect.clickable).y + (fgeom .unstick_rect.clickable).height))) |
2889 | { |
2890 | return META_FRAME_CONTROL_UNSTICK; |
2891 | } |
2892 | |
2893 | /* South resize always has priority over north resize, |
2894 | * in case of overlap. |
2895 | */ |
2896 | |
2897 | if (y >= (fgeom.height - fgeom.borders.total.bottom - RESIZE_EXTENDS15) && |
2898 | x >= (fgeom.width - fgeom.borders.total.right - RESIZE_EXTENDS15)) |
2899 | { |
2900 | if (has_vert && has_horiz) |
2901 | return META_FRAME_CONTROL_RESIZE_SE; |
2902 | else if (has_vert) |
2903 | return META_FRAME_CONTROL_RESIZE_S; |
2904 | else if (has_horiz) |
2905 | return META_FRAME_CONTROL_RESIZE_E; |
2906 | } |
2907 | else if (y >= (fgeom.height - fgeom.borders.total.bottom - RESIZE_EXTENDS15) && |
2908 | x <= (fgeom.borders.total.left + RESIZE_EXTENDS15)) |
2909 | { |
2910 | if (has_vert && has_horiz) |
2911 | return META_FRAME_CONTROL_RESIZE_SW; |
2912 | else if (has_vert) |
2913 | return META_FRAME_CONTROL_RESIZE_S; |
2914 | else if (has_horiz) |
2915 | return META_FRAME_CONTROL_RESIZE_W; |
2916 | } |
2917 | else if (y < (fgeom.borders.invisible.top + RESIZE_EXTENDS15) && |
2918 | x <= (fgeom.borders.total.left + RESIZE_EXTENDS15)) |
2919 | { |
2920 | if (has_vert && has_horiz) |
2921 | return META_FRAME_CONTROL_RESIZE_NW; |
2922 | else if (has_vert) |
2923 | return META_FRAME_CONTROL_RESIZE_N; |
2924 | else if (has_horiz) |
2925 | return META_FRAME_CONTROL_RESIZE_W; |
2926 | } |
2927 | else if (y < (fgeom.borders.invisible.top + RESIZE_EXTENDS15) && |
2928 | x >= (fgeom.width - fgeom.borders.total.right - RESIZE_EXTENDS15)) |
2929 | { |
2930 | if (has_vert && has_horiz) |
2931 | return META_FRAME_CONTROL_RESIZE_NE; |
2932 | else if (has_vert) |
2933 | return META_FRAME_CONTROL_RESIZE_N; |
2934 | else if (has_horiz) |
2935 | return META_FRAME_CONTROL_RESIZE_E; |
2936 | } |
2937 | else if (y < (fgeom.borders.invisible.top + TOP_RESIZE_HEIGHT4 * scale)) |
2938 | { |
2939 | if (has_vert) |
2940 | return META_FRAME_CONTROL_RESIZE_N; |
2941 | } |
2942 | else if (y >= (fgeom.height - fgeom.borders.total.bottom - RESIZE_EXTENDS15)) |
2943 | { |
2944 | if (has_vert) |
2945 | return META_FRAME_CONTROL_RESIZE_S; |
2946 | } |
2947 | else if (x <= fgeom.borders.total.left + RESIZE_EXTENDS15) |
2948 | { |
2949 | if (has_horiz) |
2950 | return META_FRAME_CONTROL_RESIZE_W; |
2951 | } |
2952 | else if (x >= (fgeom.width - fgeom.borders.total.right - RESIZE_EXTENDS15)) |
2953 | { |
2954 | if (has_horiz) |
2955 | return META_FRAME_CONTROL_RESIZE_E; |
2956 | } |
2957 | |
2958 | if (y >= fgeom.borders.total.top) |
2959 | return META_FRAME_CONTROL_NONE; |
2960 | else |
2961 | return META_FRAME_CONTROL_TITLE; |
2962 | } |
2963 | |
2964 | void |
2965 | meta_frames_push_delay_exposes (MetaFrames *frames) |
2966 | { |
2967 | if (frames->expose_delay_count == 0) |
2968 | { |
2969 | /* Make sure we've repainted things */ |
2970 | cdk_window_process_all_updates (); |
2971 | XFlush (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ()))); |
2972 | } |
2973 | |
2974 | frames->expose_delay_count += 1; |
2975 | } |
2976 | |
2977 | static void |
2978 | queue_pending_exposes_func (gpointer key, gpointer value, gpointer data) |
2979 | { |
2980 | MetaUIFrame *frame; |
2981 | MetaFrames *frames; |
2982 | |
2983 | frames = META_FRAMES (data)((((MetaFrames*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data)), ((meta_frames_get_type ())))))); |
2984 | frame = value; |
2985 | |
2986 | if (frame->expose_delayed) |
2987 | { |
2988 | invalidate_whole_window (frames, frame); |
2989 | frame->expose_delayed = FALSE(0); |
2990 | } |
2991 | } |
2992 | |
2993 | void |
2994 | meta_frames_pop_delay_exposes (MetaFrames *frames) |
2995 | { |
2996 | g_return_if_fail (frames->expose_delay_count > 0)do { if ((frames->expose_delay_count > 0)) { } else { g_return_if_fail_warning ("croma", ((const char*) (__func__)), "frames->expose_delay_count > 0" ); return; } } while (0); |
2997 | |
2998 | frames->expose_delay_count -= 1; |
2999 | |
3000 | if (frames->expose_delay_count == 0) |
3001 | { |
3002 | g_hash_table_foreach (frames->frames, |
3003 | queue_pending_exposes_func, |
3004 | frames); |
3005 | } |
3006 | } |
3007 | |
3008 | static void |
3009 | invalidate_whole_window (MetaFrames *frames, |
3010 | MetaUIFrame *frame) |
3011 | { |
3012 | cdk_window_invalidate_rect (frame->window, NULL((void*)0), FALSE(0)); |
3013 | invalidate_cache (frames, frame); |
3014 | } |