You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

2463 lines
72 KiB

  1. /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2. /**
  3. * SECTION:meta-window-actor
  4. * @title: MetaWindowActor
  5. * @short_description: An actor representing a top-level window in the scene graph
  6. */
  7. #include <config.h>
  8. #include <math.h>
  9. #include <X11/extensions/shape.h>
  10. #include <X11/extensions/Xcomposite.h>
  11. #include <X11/extensions/Xdamage.h>
  12. #include <X11/extensions/Xrender.h>
  13. #include <clutter/x11/clutter-x11.h>
  14. #define COGL_ENABLE_EXPERIMENTAL_API
  15. #include <cogl/cogl-texture-pixmap-x11.h>
  16. #include <gdk/gdk.h> /* for gdk_rectangle_union() */
  17. #include <meta/display.h>
  18. #include <meta/errors.h>
  19. #include "frame.h"
  20. #include <meta/window.h>
  21. #include <meta/meta-shaped-texture.h>
  22. #include "xprops.h"
  23. #include "compositor-private.h"
  24. #include "meta-shadow-factory-private.h"
  25. #include "meta-window-actor-private.h"
  26. enum {
  27. POSITION_CHANGED,
  28. SIZE_CHANGED,
  29. LAST_SIGNAL
  30. };
  31. static guint signals[LAST_SIGNAL] = {0};
  32. struct _MetaWindowActorPrivate
  33. {
  34. MetaWindow *window;
  35. Window xwindow;
  36. MetaScreen *screen;
  37. ClutterActor *actor;
  38. /* MetaShadowFactory only caches shadows that are actually in use;
  39. * to avoid unnecessary recomputation we do two things: 1) we store
  40. * both a focused and unfocused shadow for the window. If the window
  41. * doesn't have different focused and unfocused shadow parameters,
  42. * these will be the same. 2) when the shadow potentially changes we
  43. * don't immediately unreference the old shadow, we just flag it as
  44. * dirty and recompute it when we next need it (recompute_focused_shadow,
  45. * recompute_unfocused_shadow.) Because of our extraction of
  46. * size-invariant window shape, we'll often find that the new shadow
  47. * is the same as the old shadow.
  48. */
  49. MetaShadow *focused_shadow;
  50. MetaShadow *unfocused_shadow;
  51. Pixmap back_pixmap;
  52. Damage damage;
  53. guint8 opacity;
  54. guint8 shadow_opacity;
  55. gchar * desc;
  56. /* If the window is shaped, a region that matches the shape */
  57. cairo_region_t *shape_region;
  58. /* A rectangular region with the visible extents of the window */
  59. cairo_region_t *bounding_region;
  60. /* The region we should clip to when painting the shadow */
  61. cairo_region_t *shadow_clip;
  62. /* Extracted size-invariant shape used for shadows */
  63. MetaWindowShape *shadow_shape;
  64. gint last_width;
  65. gint last_height;
  66. MetaFrameBorders last_borders;
  67. gint freeze_count;
  68. char * shadow_class;
  69. /*
  70. * These need to be counters rather than flags, since more plugins
  71. * can implement same effect; the practicality of stacking effects
  72. * might be dubious, but we have to at least handle it correctly.
  73. */
  74. gint minimize_in_progress;
  75. gint maximize_in_progress;
  76. gint unmaximize_in_progress;
  77. gint tile_in_progress;
  78. gint map_in_progress;
  79. gint destroy_in_progress;
  80. guint visible : 1;
  81. guint mapped : 1;
  82. guint argb32 : 1;
  83. guint disposed : 1;
  84. guint redecorating : 1;
  85. guint needs_damage_all : 1;
  86. guint received_damage : 1;
  87. guint needs_pixmap : 1;
  88. guint needs_reshape : 1;
  89. guint recompute_focused_shadow : 1;
  90. guint recompute_unfocused_shadow : 1;
  91. guint size_changed : 1;
  92. guint needs_destroy : 1;
  93. guint no_shadow : 1;
  94. guint no_more_x_calls : 1;
  95. guint unredirected : 1;
  96. /* This is used to detect fullscreen windows that need to be unredirected */
  97. guint full_damage_frames_count;
  98. guint does_full_damage : 1;
  99. guint has_desat_effect : 1;
  100. };
  101. enum
  102. {
  103. PROP_META_WINDOW = 1,
  104. PROP_META_SCREEN,
  105. PROP_X_WINDOW,
  106. PROP_X_WINDOW_ATTRIBUTES,
  107. PROP_NO_SHADOW,
  108. PROP_SHADOW_CLASS
  109. };
  110. #define DEFAULT_SHADOW_RADIUS 12
  111. #define DEFAULT_SHADOW_X_OFFSET 0
  112. #define DEFAULT_SHADOW_Y_OFFSET 8
  113. static void meta_window_actor_dispose (GObject *object);
  114. static void meta_window_actor_finalize (GObject *object);
  115. static void meta_window_actor_constructed (GObject *object);
  116. static void meta_window_actor_set_property (GObject *object,
  117. guint prop_id,
  118. const GValue *value,
  119. GParamSpec *pspec);
  120. static void meta_window_actor_get_property (GObject *object,
  121. guint prop_id,
  122. GValue *value,
  123. GParamSpec *pspec);
  124. static void meta_window_actor_paint (ClutterActor *actor);
  125. static gboolean meta_window_actor_get_paint_volume (ClutterActor *actor,
  126. ClutterPaintVolume *volume);
  127. static void meta_window_actor_detach (MetaWindowActor *self);
  128. static gboolean meta_window_actor_has_shadow (MetaWindowActor *self);
  129. static void meta_window_actor_clear_shape_region (MetaWindowActor *self);
  130. static void meta_window_actor_clear_bounding_region (MetaWindowActor *self);
  131. static void meta_window_actor_clear_shadow_clip (MetaWindowActor *self);
  132. static void check_needs_reshape (MetaWindowActor *self);
  133. G_DEFINE_TYPE (MetaWindowActor, meta_window_actor, CLUTTER_TYPE_GROUP);
  134. static void
  135. meta_window_actor_class_init (MetaWindowActorClass *klass)
  136. {
  137. GObjectClass *object_class = G_OBJECT_CLASS (klass);
  138. ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
  139. GParamSpec *pspec;
  140. g_type_class_add_private (klass, sizeof (MetaWindowActorPrivate));
  141. object_class->dispose = meta_window_actor_dispose;
  142. object_class->finalize = meta_window_actor_finalize;
  143. object_class->set_property = meta_window_actor_set_property;
  144. object_class->get_property = meta_window_actor_get_property;
  145. object_class->constructed = meta_window_actor_constructed;
  146. actor_class->paint = meta_window_actor_paint;
  147. actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
  148. pspec = g_param_spec_object ("meta-window",
  149. "MetaWindow",
  150. "The displayed MetaWindow",
  151. META_TYPE_WINDOW,
  152. G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
  153. g_object_class_install_property (object_class,
  154. PROP_META_WINDOW,
  155. pspec);
  156. pspec = g_param_spec_pointer ("meta-screen",
  157. "MetaScreen",
  158. "MetaScreen",
  159. G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
  160. g_object_class_install_property (object_class,
  161. PROP_META_SCREEN,
  162. pspec);
  163. pspec = g_param_spec_ulong ("x-window",
  164. "Window",
  165. "Window",
  166. 0,
  167. G_MAXULONG,
  168. 0,
  169. G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
  170. g_object_class_install_property (object_class,
  171. PROP_X_WINDOW,
  172. pspec);
  173. pspec = g_param_spec_boolean ("no-shadow",
  174. "No shadow",
  175. "Do not add shaddow to this window",
  176. FALSE,
  177. G_PARAM_READWRITE);
  178. g_object_class_install_property (object_class,
  179. PROP_NO_SHADOW,
  180. pspec);
  181. pspec = g_param_spec_string ("shadow-class",
  182. "Name of the shadow class for this window.",
  183. "NULL means to use the default shadow class for this window type",
  184. NULL,
  185. G_PARAM_READWRITE);
  186. g_object_class_install_property (object_class,
  187. PROP_SHADOW_CLASS,
  188. pspec);
  189. signals[POSITION_CHANGED] =
  190. g_signal_new ("position-changed",
  191. G_TYPE_FROM_CLASS (klass),
  192. G_SIGNAL_RUN_LAST,
  193. 0, NULL, NULL, NULL,
  194. G_TYPE_NONE, 0);
  195. signals[SIZE_CHANGED] =
  196. g_signal_new ("size-changed",
  197. G_TYPE_FROM_CLASS (klass),
  198. G_SIGNAL_RUN_LAST,
  199. 0, NULL, NULL, NULL,
  200. G_TYPE_NONE, 0);
  201. }
  202. static void
  203. meta_window_actor_init (MetaWindowActor *self)
  204. {
  205. MetaWindowActorPrivate *priv;
  206. priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
  207. META_TYPE_WINDOW_ACTOR,
  208. MetaWindowActorPrivate);
  209. priv->opacity = 0xff;
  210. priv->shadow_class = NULL;
  211. priv->has_desat_effect = FALSE;
  212. }
  213. static void
  214. maybe_desaturate_window (ClutterActor *actor)
  215. {
  216. MetaWindowActor *window = META_WINDOW_ACTOR (actor);
  217. MetaWindowActorPrivate *priv = window->priv;
  218. guint8 opacity = clutter_actor_get_opacity (actor);
  219. if (opacity < 255)
  220. {
  221. if (priv->has_desat_effect)
  222. {
  223. return;
  224. }
  225. else
  226. {
  227. ClutterEffect *effect = clutter_desaturate_effect_new (0.0);
  228. clutter_actor_add_effect_with_name (actor, "desaturate-for-transparency", effect);
  229. priv->has_desat_effect = TRUE;
  230. }
  231. }
  232. else
  233. {
  234. /* This is will tend to get called fairly often - opening new windows, various
  235. events on the window, like minimizing... but it's inexpensive - if the ClutterActor
  236. priv->effects is NULL, it simply returns. By default cinnamon and muffin add no
  237. other effects except the special case of dimmed windows (attached modal dialogs), which
  238. isn't a frequent occurrence. */
  239. clutter_actor_remove_effect_by_name (actor, "desaturate-for-transparency");
  240. priv->has_desat_effect = FALSE;
  241. }
  242. }
  243. static void
  244. window_decorated_notify (MetaWindow *mw,
  245. GParamSpec *arg1,
  246. gpointer data)
  247. {
  248. MetaWindowActor *self = META_WINDOW_ACTOR (data);
  249. MetaWindowActorPrivate *priv = self->priv;
  250. MetaFrame *frame = meta_window_get_frame (mw);
  251. MetaScreen *screen = priv->screen;
  252. MetaDisplay *display = meta_screen_get_display (screen);
  253. Display *xdisplay = meta_display_get_xdisplay (display);
  254. Window new_xwindow;
  255. /*
  256. * Basically, we have to reconstruct the the internals of this object
  257. * from scratch, as everything has changed.
  258. */
  259. priv->redecorating = TRUE;
  260. if (frame)
  261. new_xwindow = meta_frame_get_xwindow (frame);
  262. else
  263. new_xwindow = meta_window_get_xwindow (mw);
  264. meta_window_actor_detach (self);
  265. /*
  266. * First of all, clean up any resources we are currently using and will
  267. * be replacing.
  268. */
  269. if (priv->damage != None)
  270. {
  271. meta_error_trap_push (display);
  272. XDamageDestroy (xdisplay, priv->damage);
  273. meta_error_trap_pop (display);
  274. priv->damage = None;
  275. }
  276. g_free (priv->desc);
  277. priv->desc = NULL;
  278. priv->xwindow = new_xwindow;
  279. /*
  280. * Recreate the contents.
  281. */
  282. meta_window_actor_constructed (G_OBJECT (self));
  283. }
  284. static void
  285. window_appears_focused_notify (MetaWindow *mw,
  286. GParamSpec *arg1,
  287. gpointer data)
  288. {
  289. clutter_actor_queue_redraw (CLUTTER_ACTOR (data));
  290. }
  291. static void
  292. clutter_actor_opacity_notify (ClutterActor *actor,
  293. GParamSpec *arg1m,
  294. gpointer data)
  295. {
  296. maybe_desaturate_window (actor);
  297. }
  298. static void
  299. meta_window_actor_constructed (GObject *object)
  300. {
  301. MetaWindowActor *self = META_WINDOW_ACTOR (object);
  302. MetaWindowActorPrivate *priv = self->priv;
  303. MetaScreen *screen = priv->screen;
  304. MetaDisplay *display = meta_screen_get_display (screen);
  305. Window xwindow = priv->xwindow;
  306. MetaWindow *window = priv->window;
  307. Display *xdisplay = meta_display_get_xdisplay (display);
  308. XRenderPictFormat *format;
  309. priv->damage = XDamageCreate (xdisplay, xwindow,
  310. XDamageReportBoundingBox);
  311. format = XRenderFindVisualFormat (xdisplay, window->xvisual);
  312. if (format && format->type == PictTypeDirect && format->direct.alphaMask)
  313. priv->argb32 = TRUE;
  314. if (!priv->actor)
  315. {
  316. priv->actor = meta_shaped_texture_new ();
  317. clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->actor);
  318. /*
  319. * Since we are holding a pointer to this actor independently of the
  320. * ClutterContainer internals, and provide a public API to access it,
  321. * add a reference here, so that if someone is messing about with us
  322. * via the container interface, we do not end up with a dangling pointer.
  323. * We will release it in dispose().
  324. */
  325. g_object_ref (priv->actor);
  326. g_signal_connect (window, "notify::decorated",
  327. G_CALLBACK (window_decorated_notify), self);
  328. g_signal_connect (window, "notify::appears-focused",
  329. G_CALLBACK (window_appears_focused_notify), self);
  330. g_signal_connect (self, "notify::opacity",
  331. G_CALLBACK (clutter_actor_opacity_notify), NULL);
  332. }
  333. else
  334. {
  335. /*
  336. * This is the case where existing window is gaining/loosing frame.
  337. * Just ensure the actor is top most (i.e., above shadow).
  338. */
  339. clutter_actor_raise_top (priv->actor);
  340. }
  341. meta_window_actor_update_opacity (self);
  342. maybe_desaturate_window (CLUTTER_ACTOR (self));
  343. priv->shape_region = cairo_region_create();
  344. }
  345. static void
  346. meta_window_actor_dispose (GObject *object)
  347. {
  348. MetaWindowActor *self = META_WINDOW_ACTOR (object);
  349. MetaWindowActorPrivate *priv = self->priv;
  350. MetaScreen *screen;
  351. MetaDisplay *display;
  352. Display *xdisplay;
  353. MetaCompScreen *info;
  354. if (priv->disposed)
  355. return;
  356. priv->disposed = TRUE;
  357. screen = priv->screen;
  358. display = meta_screen_get_display (screen);
  359. xdisplay = meta_display_get_xdisplay (display);
  360. info = meta_screen_get_compositor_data (screen);
  361. meta_window_actor_detach (self);
  362. meta_window_actor_clear_shape_region (self);
  363. meta_window_actor_clear_bounding_region (self);
  364. meta_window_actor_clear_shadow_clip (self);
  365. if (priv->shadow_class != NULL)
  366. {
  367. g_free (priv->shadow_class);
  368. priv->shadow_class = NULL;
  369. }
  370. if (priv->focused_shadow != NULL)
  371. {
  372. meta_shadow_unref (priv->focused_shadow);
  373. priv->focused_shadow = NULL;
  374. }
  375. if (priv->unfocused_shadow != NULL)
  376. {
  377. meta_shadow_unref (priv->unfocused_shadow);
  378. priv->unfocused_shadow = NULL;
  379. }
  380. if (priv->shadow_shape != NULL)
  381. {
  382. meta_window_shape_unref (priv->shadow_shape);
  383. priv->shadow_shape = NULL;
  384. }
  385. if (priv->damage != None)
  386. {
  387. meta_error_trap_push (display);
  388. XDamageDestroy (xdisplay, priv->damage);
  389. meta_error_trap_pop (display);
  390. priv->damage = None;
  391. }
  392. info->windows = g_list_remove (info->windows, (gconstpointer) self);
  393. if (priv->window)
  394. {
  395. g_object_unref (priv->window);
  396. priv->window = NULL;
  397. }
  398. /*
  399. * Release the extra reference we took on the actor.
  400. */
  401. g_object_unref (priv->actor);
  402. priv->actor = NULL;
  403. G_OBJECT_CLASS (meta_window_actor_parent_class)->dispose (object);
  404. }
  405. static void
  406. meta_window_actor_finalize (GObject *object)
  407. {
  408. MetaWindowActor *self = META_WINDOW_ACTOR (object);
  409. MetaWindowActorPrivate *priv = self->priv;
  410. g_free (priv->desc);
  411. G_OBJECT_CLASS (meta_window_actor_parent_class)->finalize (object);
  412. }
  413. static void
  414. meta_window_actor_set_property (GObject *object,
  415. guint prop_id,
  416. const GValue *value,
  417. GParamSpec *pspec)
  418. {
  419. MetaWindowActor *self = META_WINDOW_ACTOR (object);
  420. MetaWindowActorPrivate *priv = self->priv;
  421. switch (prop_id)
  422. {
  423. case PROP_META_WINDOW:
  424. {
  425. if (priv->window)
  426. g_object_unref (priv->window);
  427. priv->window = g_value_dup_object (value);
  428. }
  429. break;
  430. case PROP_META_SCREEN:
  431. priv->screen = g_value_get_pointer (value);
  432. break;
  433. case PROP_X_WINDOW:
  434. priv->xwindow = g_value_get_ulong (value);
  435. break;
  436. case PROP_NO_SHADOW:
  437. {
  438. gboolean newv = g_value_get_boolean (value);
  439. if (newv == priv->no_shadow)
  440. return;
  441. priv->no_shadow = newv;
  442. meta_window_actor_invalidate_shadow (self);
  443. }
  444. break;
  445. case PROP_SHADOW_CLASS:
  446. {
  447. const char *newv = g_value_get_string (value);
  448. if (g_strcmp0 (newv, priv->shadow_class) == 0)
  449. return;
  450. g_free (priv->shadow_class);
  451. priv->shadow_class = g_strdup (newv);
  452. meta_window_actor_invalidate_shadow (self);
  453. }
  454. break;
  455. default:
  456. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  457. break;
  458. }
  459. }
  460. static void
  461. meta_window_actor_get_property (GObject *object,
  462. guint prop_id,
  463. GValue *value,
  464. GParamSpec *pspec)
  465. {
  466. MetaWindowActorPrivate *priv = META_WINDOW_ACTOR (object)->priv;
  467. switch (prop_id)
  468. {
  469. case PROP_META_WINDOW:
  470. g_value_set_object (value, priv->window);
  471. break;
  472. case PROP_META_SCREEN:
  473. g_value_set_pointer (value, priv->screen);
  474. break;
  475. case PROP_X_WINDOW:
  476. g_value_set_ulong (value, priv->xwindow);
  477. break;
  478. case PROP_NO_SHADOW:
  479. g_value_set_boolean (value, priv->no_shadow);
  480. break;
  481. case PROP_SHADOW_CLASS:
  482. g_value_set_string (value, priv->shadow_class);
  483. break;
  484. default:
  485. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  486. break;
  487. }
  488. }
  489. static const char *
  490. meta_window_actor_get_shadow_class (MetaWindowActor *self)
  491. {
  492. MetaWindowActorPrivate *priv = self->priv;
  493. if (priv->shadow_class != NULL)
  494. return priv->shadow_class;
  495. else
  496. {
  497. MetaWindowType window_type = meta_window_get_window_type (priv->window);
  498. switch (window_type)
  499. {
  500. case META_WINDOW_DROPDOWN_MENU:
  501. return "dropdown-menu";
  502. case META_WINDOW_POPUP_MENU:
  503. return "popup-menu";
  504. default:
  505. {
  506. MetaFrameType frame_type = meta_window_get_frame_type (priv->window);
  507. return meta_frame_type_to_string (frame_type);
  508. }
  509. }
  510. }
  511. }
  512. static void
  513. meta_window_actor_get_shadow_params (MetaWindowActor *self,
  514. gboolean appears_focused,
  515. MetaShadowParams *params)
  516. {
  517. const char *shadow_class = meta_window_actor_get_shadow_class (self);
  518. meta_shadow_factory_get_params (meta_shadow_factory_get_default (),
  519. shadow_class, appears_focused,
  520. params);
  521. }
  522. LOCAL_SYMBOL void
  523. meta_window_actor_get_shape_bounds (MetaWindowActor *self,
  524. cairo_rectangle_int_t *bounds)
  525. {
  526. MetaWindowActorPrivate *priv = self->priv;
  527. /* We need to be defensive here because there are corner cases
  528. * where getting the shape fails on a window being destroyed
  529. * and similar.
  530. */
  531. if (priv->shape_region)
  532. cairo_region_get_extents (priv->shape_region, bounds);
  533. else if (priv->bounding_region)
  534. cairo_region_get_extents (priv->bounding_region, bounds);
  535. else
  536. bounds->x = bounds->y = bounds->width = bounds->height = 0;
  537. }
  538. static void
  539. meta_window_actor_get_shadow_bounds (MetaWindowActor *self,
  540. gboolean appears_focused,
  541. cairo_rectangle_int_t *bounds)
  542. {
  543. MetaWindowActorPrivate *priv = self->priv;
  544. MetaShadow *shadow = appears_focused ? priv->focused_shadow : priv->unfocused_shadow;
  545. cairo_rectangle_int_t shape_bounds;
  546. MetaShadowParams params;
  547. meta_window_actor_get_shape_bounds (self, &shape_bounds);
  548. meta_window_actor_get_shadow_params (self, appears_focused, &params);
  549. meta_shadow_get_bounds (shadow,
  550. params.x_offset + shape_bounds.x,
  551. params.y_offset + shape_bounds.y,
  552. shape_bounds.width,
  553. shape_bounds.height,
  554. bounds);
  555. }
  556. /* If we have an ARGB32 window that we decorate with a frame, it's
  557. * probably something like a translucent terminal - something where
  558. * the alpha channel represents transparency rather than a shape. We
  559. * don't want to show the shadow through the translucent areas since
  560. * the shadow is wrong for translucent windows (it should be
  561. * translucent itself and colored), and not only that, will /look/
  562. * horribly wrong - a misplaced big black blob. As a hack, what we
  563. * want to do is just draw the shadow as normal outside the frame, and
  564. * inside the frame draw no shadow. This is also not even close to
  565. * the right result, but looks OK. We also apply this approach to
  566. * windows set to be partially translucent with _NET_WM_WINDOW_OPACITY.
  567. */
  568. static gboolean
  569. clip_shadow_under_window (MetaWindowActor *self)
  570. {
  571. MetaWindowActorPrivate *priv = self->priv;
  572. return (priv->argb32 || priv->opacity != 0xff) && priv->window->frame;
  573. }
  574. static void
  575. meta_window_actor_paint (ClutterActor *actor)
  576. {
  577. MetaWindowActor *self = META_WINDOW_ACTOR (actor);
  578. MetaWindowActorPrivate *priv = self->priv;
  579. gboolean appears_focused = meta_window_appears_focused (priv->window);
  580. MetaShadow *shadow = appears_focused ? priv->focused_shadow : priv->unfocused_shadow;
  581. if (g_getenv ("MUFFIN_NO_SHADOWS")) {
  582. shadow = NULL;
  583. }
  584. if (shadow != NULL)
  585. {
  586. MetaShadowParams params;
  587. cairo_rectangle_int_t shape_bounds;
  588. cairo_region_t *clip = priv->shadow_clip;
  589. meta_window_actor_get_shape_bounds (self, &shape_bounds);
  590. meta_window_actor_get_shadow_params (self, appears_focused, &params);
  591. /* The frame bounds are already subtracted from priv->shadow_clip
  592. * if that exists.
  593. */
  594. if (!clip && clip_shadow_under_window (self))
  595. {
  596. cairo_region_t *frame_bounds = meta_window_get_frame_bounds (priv->window);
  597. cairo_rectangle_int_t bounds;
  598. meta_window_actor_get_shadow_bounds (self, appears_focused, &bounds);
  599. clip = cairo_region_create_rectangle (&bounds);
  600. cairo_region_subtract (clip, frame_bounds);
  601. }
  602. meta_shadow_paint (shadow,
  603. params.x_offset + shape_bounds.x,
  604. params.y_offset + shape_bounds.y,
  605. shape_bounds.width,
  606. shape_bounds.height,
  607. (clutter_actor_get_paint_opacity (actor) * params.opacity * priv->opacity) / (255 * 255),
  608. clip,
  609. clip_shadow_under_window (self)); /* clip_strictly - not just as an optimization */
  610. if (clip && clip != priv->shadow_clip)
  611. cairo_region_destroy (clip);
  612. }
  613. CLUTTER_ACTOR_CLASS (meta_window_actor_parent_class)->paint (actor);
  614. }
  615. static gboolean
  616. meta_window_actor_get_paint_volume (ClutterActor *actor,
  617. ClutterPaintVolume *volume)
  618. {
  619. MetaWindowActor *self = META_WINDOW_ACTOR (actor);
  620. MetaWindowActorPrivate *priv = self->priv;
  621. cairo_rectangle_int_t bounds;
  622. gboolean appears_focused = meta_window_appears_focused (priv->window);
  623. ClutterVertex origin;
  624. /* The paint volume is computed before paint functions are called
  625. * so our bounds might not be updated yet. Force an update. */
  626. meta_window_actor_pre_paint (self);
  627. meta_window_actor_get_shape_bounds (self, &bounds);
  628. if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
  629. {
  630. cairo_rectangle_int_t shadow_bounds;
  631. /* We could compute an full clip region as we do for the window
  632. * texture, but the shadow is relatively cheap to draw, and
  633. * a little more complex to clip, so we just catch the case where
  634. * the shadow is completely obscured and doesn't need to be drawn
  635. * at all.
  636. */
  637. meta_window_actor_get_shadow_bounds (self, appears_focused, &shadow_bounds);
  638. gdk_rectangle_union (&bounds, &shadow_bounds, &bounds);
  639. }
  640. origin.x = bounds.x;
  641. origin.y = bounds.y;
  642. origin.z = 0.0f;
  643. clutter_paint_volume_set_origin (volume, &origin);
  644. clutter_paint_volume_set_width (volume, bounds.width);
  645. clutter_paint_volume_set_height (volume, bounds.height);
  646. return TRUE;
  647. }
  648. static gboolean
  649. meta_window_actor_has_shadow (MetaWindowActor *self)
  650. {
  651. MetaWindowActorPrivate *priv = self->priv;
  652. MetaWindowType window_type = meta_window_get_window_type (priv->window);
  653. if (priv->no_shadow)
  654. return FALSE;
  655. /* Leaving out shadows for maximized and fullscreen windows is an effeciency
  656. * win and also prevents the unsightly effect of the shadow of maximized
  657. * window appearing on an adjacent window */
  658. if ((meta_window_get_maximized (priv->window) == (META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL)) ||
  659. meta_window_is_fullscreen (priv->window))
  660. return FALSE;
  661. /* Don't shadow tiled windows of any type */
  662. if (meta_window_get_tile_type (priv->window) != META_WINDOW_TILE_TYPE_NONE)
  663. return FALSE;
  664. /*
  665. * Always put a shadow around windows with a frame - This should override
  666. * the restriction about not putting a shadow around ARGB windows.
  667. */
  668. if (priv->window)
  669. {
  670. if (meta_window_get_frame (priv->window))
  671. return TRUE;
  672. }
  673. /*
  674. * Do not add shadows to ARGB windows; eventually we should generate a
  675. * shadow from the input shape for such windows.
  676. */
  677. if (priv->argb32 || priv->opacity != 0xff)
  678. return FALSE;
  679. /*
  680. * Add shadows to override redirect windows (e.g., Gtk menus).
  681. */
  682. if (priv->window->override_redirect)
  683. return TRUE;
  684. /*
  685. * Don't put shadow around DND icon windows
  686. */
  687. if (window_type == META_WINDOW_DND ||
  688. window_type == META_WINDOW_DESKTOP)
  689. return FALSE;
  690. if (window_type == META_WINDOW_MENU
  691. #if 0
  692. || window_type == META_WINDOW_DROPDOWN_MENU
  693. #endif
  694. )
  695. return TRUE;
  696. #if 0
  697. if (window_type == META_WINDOW_TOOLTIP)
  698. return TRUE;
  699. #endif
  700. return FALSE;
  701. }
  702. /**
  703. * meta_window_actor_get_x_window: (skip)
  704. *
  705. */
  706. Window
  707. meta_window_actor_get_x_window (MetaWindowActor *self)
  708. {
  709. if (!self)
  710. return None;
  711. return self->priv->xwindow;
  712. }
  713. /**
  714. * meta_window_actor_get_meta_window:
  715. *
  716. * Gets the #MetaWindow object that the the #MetaWindowActor is displaying
  717. *
  718. * Return value: (transfer none): the displayed #MetaWindow
  719. */
  720. MetaWindow *
  721. meta_window_actor_get_meta_window (MetaWindowActor *self)
  722. {
  723. return self->priv->window;
  724. }
  725. /**
  726. * meta_window_actor_get_texture:
  727. *
  728. * Gets the ClutterActor that is used to display the contents of the window
  729. *
  730. * Return value: (transfer none): the #ClutterActor for the contents
  731. */
  732. ClutterActor *
  733. meta_window_actor_get_texture (MetaWindowActor *self)
  734. {
  735. return self->priv->actor;
  736. }
  737. /**
  738. * meta_window_actor_is_destroyed:
  739. *
  740. * Gets whether the X window that the actor was displaying has been destroyed
  741. *
  742. * Return value: %TRUE when the window is destroyed, otherwise %FALSE
  743. */
  744. gboolean
  745. meta_window_actor_is_destroyed (MetaWindowActor *self)
  746. {
  747. return self->priv->disposed;
  748. }
  749. gboolean
  750. meta_window_actor_is_override_redirect (MetaWindowActor *self)
  751. {
  752. return meta_window_is_override_redirect (self->priv->window);
  753. }
  754. const char *meta_window_actor_get_description (MetaWindowActor *self)
  755. {
  756. /*
  757. * For windows managed by the WM, we just defer to the WM for the window
  758. * description. For override-redirect windows, we create the description
  759. * ourselves, but only on demand.
  760. */
  761. if (self->priv->window)
  762. return meta_window_get_description (self->priv->window);
  763. if (G_UNLIKELY (self->priv->desc == NULL))
  764. {
  765. self->priv->desc = g_strdup_printf ("Override Redirect (0x%x)",
  766. (guint) self->priv->xwindow);
  767. }
  768. return self->priv->desc;
  769. }
  770. /**
  771. * meta_window_actor_get_workspace:
  772. * @self: #MetaWindowActor
  773. *
  774. * Returns the index of workspace on which this window is located; if the
  775. * window is sticky, or is not currently located on any workspace, returns -1.
  776. * This function is deprecated and should not be used in newly written code;
  777. * meta_window_get_workspace() instead.
  778. *
  779. * Return value: (transfer none): index of workspace on which this window is
  780. * located.
  781. */
  782. gint
  783. meta_window_actor_get_workspace (MetaWindowActor *self)
  784. {
  785. MetaWindowActorPrivate *priv;
  786. MetaWorkspace *workspace;
  787. if (!self)
  788. return -1;
  789. priv = self->priv;
  790. if (!priv->window || meta_window_is_on_all_workspaces (priv->window))
  791. return -1;
  792. workspace = meta_window_get_workspace (priv->window);
  793. if (!workspace)
  794. return -1;
  795. return meta_workspace_index (workspace);
  796. }
  797. gboolean
  798. meta_window_actor_showing_on_its_workspace (MetaWindowActor *self)
  799. {
  800. if (!self)
  801. return FALSE;
  802. /* If override redirect: */
  803. if (!self->priv->window)
  804. return TRUE;
  805. return meta_window_showing_on_its_workspace (self->priv->window);
  806. }
  807. static void
  808. meta_window_actor_freeze (MetaWindowActor *self)
  809. {
  810. self->priv->freeze_count++;
  811. }
  812. static void
  813. meta_window_actor_damage_all (MetaWindowActor *self)
  814. {
  815. MetaWindowActorPrivate *priv = self->priv;
  816. CoglHandle texture;
  817. if (!priv->needs_damage_all)
  818. return;
  819. texture = meta_shaped_texture_get_texture (META_SHAPED_TEXTURE (priv->actor));
  820. if (!priv->mapped || priv->needs_pixmap)
  821. return;
  822. meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor),
  823. 0, 0,
  824. cogl_texture_get_width (texture),
  825. cogl_texture_get_height (texture));
  826. priv->needs_damage_all = FALSE;
  827. }
  828. static void
  829. meta_window_actor_thaw (MetaWindowActor *self)
  830. {
  831. self->priv->freeze_count--;
  832. if (G_UNLIKELY (self->priv->freeze_count < 0))
  833. {
  834. g_warning ("Error in freeze/thaw accounting.");
  835. self->priv->freeze_count = 0;
  836. return;
  837. }
  838. if (self->priv->freeze_count)
  839. return;
  840. /* Since we ignore damage events while a window is frozen for certain effects
  841. * we may need to issue an update_area() covering the whole pixmap if we
  842. * don't know what real damage has happened. */
  843. if (self->priv->needs_damage_all)
  844. meta_window_actor_damage_all (self);
  845. }
  846. LOCAL_SYMBOL gboolean
  847. meta_window_actor_effect_in_progress (MetaWindowActor *self)
  848. {
  849. return (self->priv->minimize_in_progress ||
  850. self->priv->maximize_in_progress ||
  851. self->priv->unmaximize_in_progress ||
  852. self->priv->map_in_progress ||
  853. self->priv->tile_in_progress ||
  854. self->priv->destroy_in_progress);
  855. }
  856. static void
  857. meta_window_actor_queue_create_pixmap (MetaWindowActor *self)
  858. {
  859. MetaWindowActorPrivate *priv = self->priv;
  860. priv->needs_pixmap = TRUE;
  861. if (!priv->mapped)
  862. return;
  863. /* This will cause the compositor paint function to be run
  864. * if the actor is visible or a clone of the actor is visible.
  865. * if the actor isn't visible in any way, then we don't
  866. * need to repair the window anyways, and can wait until
  867. * the stage is redrawn for some other reason
  868. *
  869. * The compositor paint function repairs all windows.
  870. */
  871. clutter_actor_queue_redraw (priv->actor);
  872. }
  873. static gboolean
  874. is_freeze_thaw_effect (gulong event)
  875. {
  876. switch (event)
  877. {
  878. case META_PLUGIN_DESTROY:
  879. case META_PLUGIN_MAXIMIZE:
  880. case META_PLUGIN_UNMAXIMIZE:
  881. case META_PLUGIN_TILE:
  882. return TRUE;
  883. break;
  884. default:
  885. return FALSE;
  886. }
  887. }
  888. static gboolean
  889. start_simple_effect (MetaWindowActor *self,
  890. gulong event)
  891. {
  892. MetaWindowActorPrivate *priv = self->priv;
  893. MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
  894. gint *counter = NULL;
  895. gboolean use_freeze_thaw = FALSE;
  896. if (!info->plugin_mgr)
  897. return FALSE;
  898. switch (event)
  899. {
  900. case META_PLUGIN_MINIMIZE:
  901. counter = &priv->minimize_in_progress;
  902. break;
  903. case META_PLUGIN_MAP:
  904. counter = &priv->map_in_progress;
  905. break;
  906. case META_PLUGIN_DESTROY:
  907. counter = &priv->destroy_in_progress;
  908. break;
  909. case META_PLUGIN_UNMAXIMIZE:
  910. case META_PLUGIN_MAXIMIZE:
  911. case META_PLUGIN_SWITCH_WORKSPACE:
  912. case META_PLUGIN_TILE:
  913. g_assert_not_reached ();
  914. break;
  915. }
  916. g_assert (counter);
  917. use_freeze_thaw = is_freeze_thaw_effect (event);
  918. if (use_freeze_thaw)
  919. meta_window_actor_freeze (self);
  920. (*counter)++;
  921. if (!meta_plugin_manager_event_simple (info->plugin_mgr,
  922. self,
  923. event))
  924. {
  925. (*counter)--;
  926. if (use_freeze_thaw)
  927. meta_window_actor_thaw (self);
  928. return FALSE;
  929. }
  930. return TRUE;
  931. }
  932. static void
  933. meta_window_actor_after_effects (MetaWindowActor *self)
  934. {
  935. MetaWindowActorPrivate *priv = self->priv;
  936. if (priv->needs_destroy)
  937. {
  938. clutter_actor_destroy (CLUTTER_ACTOR (self));
  939. return;
  940. }
  941. meta_window_actor_sync_visibility (self);
  942. meta_window_actor_sync_actor_position (self);
  943. if (!meta_window_is_mapped (priv->window))
  944. meta_window_actor_detach (self);
  945. if (priv->needs_pixmap)
  946. clutter_actor_queue_redraw (priv->actor);
  947. }
  948. LOCAL_SYMBOL void
  949. meta_window_actor_effect_completed (MetaWindowActor *self,
  950. gulong event)
  951. {
  952. MetaWindowActorPrivate *priv = self->priv;
  953. /* NB: Keep in mind that when effects get completed it possible
  954. * that the corresponding MetaWindow may have be been destroyed.
  955. * In this case priv->window will == NULL */
  956. switch (event)
  957. {
  958. case META_PLUGIN_MINIMIZE:
  959. {
  960. priv->minimize_in_progress--;
  961. if (priv->minimize_in_progress < 0)
  962. {
  963. g_warning ("Error in minimize accounting.");
  964. priv->minimize_in_progress = 0;
  965. }
  966. }
  967. break;
  968. case META_PLUGIN_MAP:
  969. /*
  970. * Make sure that the actor is at the correct place in case
  971. * the plugin fscked.
  972. */
  973. priv->map_in_progress--;
  974. if (priv->map_in_progress < 0)
  975. {
  976. g_warning ("Error in map accounting.");
  977. priv->map_in_progress = 0;
  978. }
  979. break;
  980. case META_PLUGIN_DESTROY:
  981. priv->destroy_in_progress--;
  982. if (priv->destroy_in_progress < 0)
  983. {
  984. g_warning ("Error in destroy accounting.");
  985. priv->destroy_in_progress = 0;
  986. }
  987. break;
  988. case META_PLUGIN_UNMAXIMIZE:
  989. priv->unmaximize_in_progress--;
  990. if (priv->unmaximize_in_progress < 0)
  991. {
  992. g_warning ("Error in unmaximize accounting.");
  993. priv->unmaximize_in_progress = 0;
  994. }
  995. break;
  996. case META_PLUGIN_MAXIMIZE:
  997. priv->maximize_in_progress--;
  998. if (priv->maximize_in_progress < 0)
  999. {
  1000. g_warning ("Error in maximize accounting.");
  1001. priv->maximize_in_progress = 0;
  1002. }
  1003. break;
  1004. case META_PLUGIN_TILE:
  1005. priv->tile_in_progress--;
  1006. if (priv->tile_in_progress < 0)
  1007. {
  1008. g_warning ("Error in tile accounting.");
  1009. priv->tile_in_progress = 0;
  1010. }
  1011. break;
  1012. case META_PLUGIN_SWITCH_WORKSPACE:
  1013. g_assert_not_reached ();
  1014. break;
  1015. }
  1016. if (is_freeze_thaw_effect (event))
  1017. meta_window_actor_thaw (self);
  1018. if (!meta_window_actor_effect_in_progress (self))
  1019. meta_window_actor_after_effects (self);
  1020. }
  1021. /* Called to drop our reference to a window backing pixmap that we
  1022. * previously obtained with XCompositeNameWindowPixmap. We do this
  1023. * when the window is unmapped or when we want to update to a new
  1024. * pixmap for a new size.
  1025. */
  1026. static void
  1027. meta_window_actor_detach (MetaWindowActor *self)
  1028. {
  1029. MetaWindowActorPrivate *priv = self->priv;
  1030. MetaScreen *screen = priv->screen;
  1031. MetaDisplay *display = meta_screen_get_display (screen);
  1032. Display *xdisplay = meta_display_get_xdisplay (display);
  1033. if (!priv->back_pixmap)
  1034. return;
  1035. /* Get rid of all references to the pixmap before freeing it; it's unclear whether
  1036. * you are supposed to be able to free a GLXPixmap after freeing the underlying
  1037. * pixmap, but it certainly doesn't work with current DRI/Mesa
  1038. */
  1039. meta_shaped_texture_set_pixmap (META_SHAPED_TEXTURE (priv->actor),
  1040. None);
  1041. cogl_flush();
  1042. XFreePixmap (xdisplay, priv->back_pixmap);
  1043. priv->back_pixmap = None;
  1044. meta_window_actor_queue_create_pixmap (self);
  1045. }
  1046. LOCAL_SYMBOL gboolean
  1047. meta_window_actor_should_unredirect (MetaWindowActor *self)
  1048. {
  1049. MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
  1050. MetaWindowActorPrivate *priv = self->priv;
  1051. if (meta_window_requested_dont_bypass_compositor (metaWindow))
  1052. return FALSE;
  1053. if (priv->opacity != 0xff)
  1054. return FALSE;
  1055. if (metaWindow->has_shape)
  1056. return FALSE;
  1057. if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow))
  1058. return FALSE;
  1059. if (!meta_window_is_monitor_sized (metaWindow))
  1060. return FALSE;
  1061. if (!meta_prefs_get_unredirect_fullscreen_windows())
  1062. return FALSE;
  1063. if (meta_window_requested_bypass_compositor (metaWindow))
  1064. return TRUE;
  1065. if (meta_window_is_override_redirect (metaWindow))
  1066. return TRUE;
  1067. if (priv->does_full_damage)
  1068. return TRUE;
  1069. return FALSE;
  1070. }
  1071. LOCAL_SYMBOL void
  1072. meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state)
  1073. {
  1074. MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
  1075. MetaDisplay *display = meta_window_get_display (metaWindow);
  1076. Display *xdisplay = meta_display_get_xdisplay (display);
  1077. Window xwin = meta_window_actor_get_x_window (self);
  1078. if (state)
  1079. {
  1080. meta_error_trap_push (display);
  1081. XCompositeRedirectWindow (xdisplay, xwin, CompositeRedirectManual);
  1082. meta_error_trap_pop (display);
  1083. meta_window_actor_detach (self);
  1084. self->priv->unredirected = FALSE;
  1085. }
  1086. else
  1087. {
  1088. meta_error_trap_push (display);
  1089. XCompositeUnredirectWindow (xdisplay, xwin, CompositeRedirectManual);
  1090. meta_error_trap_pop (display);
  1091. self->priv->unredirected = TRUE;
  1092. }
  1093. }
  1094. LOCAL_SYMBOL void
  1095. meta_window_actor_destroy (MetaWindowActor *self)
  1096. {
  1097. MetaWindow *window;
  1098. MetaCompScreen *info;
  1099. MetaWindowActorPrivate *priv;
  1100. MetaWindowType window_type;
  1101. priv = self->priv;
  1102. window = priv->window;
  1103. window_type = meta_window_get_window_type (window);
  1104. meta_window_set_compositor_private (window, NULL);
  1105. /*
  1106. * We remove the window from internal lookup hashes and thus any other
  1107. * unmap events etc fail
  1108. */
  1109. info = meta_screen_get_compositor_data (priv->screen);
  1110. info->windows = g_list_remove (info->windows, (gconstpointer) self);
  1111. if (window_type == META_WINDOW_DROPDOWN_MENU ||
  1112. window_type == META_WINDOW_POPUP_MENU ||
  1113. window_type == META_WINDOW_TOOLTIP ||
  1114. window_type == META_WINDOW_NOTIFICATION ||
  1115. window_type == META_WINDOW_COMBO ||
  1116. window_type == META_WINDOW_DND ||
  1117. window_type == META_WINDOW_OVERRIDE_OTHER)
  1118. {
  1119. /*
  1120. * No effects, just kill it.
  1121. */
  1122. clutter_actor_destroy (CLUTTER_ACTOR (self));
  1123. return;
  1124. }
  1125. priv->needs_destroy = TRUE;
  1126. /*
  1127. * Once the window destruction is initiated we can no longer perform any
  1128. * furter X-based operations. For example, if we have a Map effect running,
  1129. * we cannot query the window geometry once the effect completes. So, flag
  1130. * this.
  1131. */
  1132. priv->no_more_x_calls = TRUE;
  1133. if (!meta_window_actor_effect_in_progress (self))
  1134. clutter_actor_destroy (CLUTTER_ACTOR (self));
  1135. }
  1136. LOCAL_SYMBOL void
  1137. meta_window_actor_sync_actor_position (MetaWindowActor *self)
  1138. {
  1139. MetaWindowActorPrivate *priv = self->priv;
  1140. MetaRectangle window_rect;
  1141. meta_window_get_input_rect (priv->window, &window_rect);
  1142. if (priv->last_width != window_rect.width ||
  1143. priv->last_height != window_rect.height)
  1144. {
  1145. priv->size_changed = TRUE;
  1146. meta_window_actor_queue_create_pixmap (self);
  1147. priv->last_width = window_rect.width;
  1148. priv->last_height = window_rect.height;
  1149. }
  1150. if (meta_window_actor_effect_in_progress (self))
  1151. return;
  1152. clutter_actor_set_position (CLUTTER_ACTOR (self),
  1153. window_rect.x, window_rect.y);
  1154. clutter_actor_set_size (CLUTTER_ACTOR (self),
  1155. window_rect.width, window_rect.height);
  1156. g_signal_emit (self, signals[POSITION_CHANGED], 0);
  1157. }
  1158. void
  1159. meta_window_actor_show (MetaWindowActor *self,
  1160. MetaCompEffect effect)
  1161. {
  1162. MetaWindowActorPrivate *priv;
  1163. MetaCompScreen *info;
  1164. gulong event;
  1165. priv = self->priv;
  1166. info = meta_screen_get_compositor_data (priv->screen);
  1167. g_return_if_fail (!priv->visible);
  1168. self->priv->visible = TRUE;
  1169. event = 0;
  1170. switch (effect)
  1171. {
  1172. case META_COMP_EFFECT_CREATE:
  1173. event = META_PLUGIN_MAP;
  1174. break;
  1175. case META_COMP_EFFECT_UNMINIMIZE:
  1176. /* FIXME: should have META_PLUGIN_UNMINIMIZE */
  1177. event = META_PLUGIN_MAP;
  1178. break;
  1179. case META_COMP_EFFECT_NONE:
  1180. break;
  1181. case META_COMP_EFFECT_DESTROY:
  1182. case META_COMP_EFFECT_MINIMIZE:
  1183. g_assert_not_reached();
  1184. }
  1185. if (priv->redecorating ||
  1186. info->switch_workspace_in_progress ||
  1187. event == 0 ||
  1188. !start_simple_effect (self, event))
  1189. {
  1190. clutter_actor_show_all (CLUTTER_ACTOR (self));
  1191. priv->redecorating = FALSE;
  1192. }
  1193. }
  1194. LOCAL_SYMBOL void
  1195. meta_window_actor_hide (MetaWindowActor *self,
  1196. MetaCompEffect effect)
  1197. {
  1198. MetaWindowActorPrivate *priv;
  1199. MetaCompScreen *info;
  1200. gulong event;
  1201. priv = self->priv;
  1202. info = meta_screen_get_compositor_data (priv->screen);
  1203. g_return_if_fail (priv->visible || (!priv->visible && meta_window_is_attached_dialog (priv->window)));
  1204. priv->visible = FALSE;
  1205. /* If a plugin is animating a workspace transition, we have to
  1206. * hold off on hiding the window, and do it after the workspace
  1207. * switch completes
  1208. */
  1209. if (info->switch_workspace_in_progress)
  1210. return;
  1211. event = 0;
  1212. switch (effect)
  1213. {
  1214. case META_COMP_EFFECT_DESTROY:
  1215. event = META_PLUGIN_DESTROY;
  1216. break;
  1217. case META_COMP_EFFECT_MINIMIZE:
  1218. event = META_PLUGIN_MINIMIZE;
  1219. break;
  1220. case META_COMP_EFFECT_NONE:
  1221. break;
  1222. case META_COMP_EFFECT_UNMINIMIZE:
  1223. case META_COMP_EFFECT_CREATE:
  1224. g_assert_not_reached();
  1225. }
  1226. if (event == 0 ||
  1227. !start_simple_effect (self, event))
  1228. clutter_actor_hide (CLUTTER_ACTOR (self));
  1229. }
  1230. LOCAL_SYMBOL void
  1231. meta_window_actor_maximize (MetaWindowActor *self,
  1232. MetaRectangle *old_rect,
  1233. MetaRectangle *new_rect)
  1234. {
  1235. MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
  1236. /* The window has already been resized (in order to compute new_rect),
  1237. * which by side effect caused the actor to be resized. Restore it to the
  1238. * old size and position */
  1239. clutter_actor_set_position (CLUTTER_ACTOR (self), old_rect->x, old_rect->y);
  1240. clutter_actor_set_size (CLUTTER_ACTOR (self), old_rect->width, old_rect->height);
  1241. self->priv->maximize_in_progress++;
  1242. meta_window_actor_freeze (self);
  1243. if (!info->plugin_mgr ||
  1244. !meta_plugin_manager_event_maximize (info->plugin_mgr,
  1245. self,
  1246. META_PLUGIN_MAXIMIZE,
  1247. new_rect->x, new_rect->y,
  1248. new_rect->width, new_rect->height))
  1249. {
  1250. self->priv->maximize_in_progress--;
  1251. meta_window_actor_thaw (self);
  1252. }
  1253. }
  1254. LOCAL_SYMBOL void
  1255. meta_window_actor_unmaximize (MetaWindowActor *self,
  1256. MetaRectangle *old_rect,
  1257. MetaRectangle *new_rect)
  1258. {
  1259. MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
  1260. /* The window has already been resized (in order to compute new_rect),
  1261. * which by side effect caused the actor to be resized. Restore it to the
  1262. * old size and position */
  1263. clutter_actor_set_position (CLUTTER_ACTOR (self), old_rect->x, old_rect->y);
  1264. clutter_actor_set_size (CLUTTER_ACTOR (self), old_rect->width, old_rect->height);
  1265. self->priv->unmaximize_in_progress++;
  1266. meta_window_actor_freeze (self);
  1267. if (!info->plugin_mgr ||
  1268. !meta_plugin_manager_event_maximize (info->plugin_mgr,
  1269. self,
  1270. META_PLUGIN_UNMAXIMIZE,
  1271. new_rect->x, new_rect->y,
  1272. new_rect->width, new_rect->height))
  1273. {
  1274. self->priv->unmaximize_in_progress--;
  1275. meta_window_actor_thaw (self);
  1276. }
  1277. }
  1278. LOCAL_SYMBOL void
  1279. meta_window_actor_tile (MetaWindowActor *self,
  1280. MetaRectangle *old_rect,
  1281. MetaRectangle *new_rect)
  1282. {
  1283. MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
  1284. /* The window has already been resized (in order to compute new_rect),
  1285. * which by side effect caused the actor to be resized. Restore it to the
  1286. * old size and position */
  1287. clutter_actor_set_position (CLUTTER_ACTOR (self), old_rect->x, old_rect->y);
  1288. clutter_actor_set_size (CLUTTER_ACTOR (self), old_rect->width, old_rect->height);
  1289. self->priv->tile_in_progress++;
  1290. meta_window_actor_freeze (self);
  1291. if (!info->plugin_mgr ||
  1292. !meta_plugin_manager_event_maximize (info->plugin_mgr,
  1293. self,
  1294. META_PLUGIN_TILE,
  1295. new_rect->x, new_rect->y,
  1296. new_rect->width, new_rect->height))
  1297. {
  1298. self->priv->tile_in_progress--;
  1299. meta_window_actor_thaw (self);
  1300. }
  1301. }
  1302. LOCAL_SYMBOL MetaWindowActor *
  1303. meta_window_actor_new (MetaWindow *window)
  1304. {
  1305. MetaScreen *screen = meta_window_get_screen (window);
  1306. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1307. MetaWindowActor *self;
  1308. MetaWindowActorPrivate *priv;
  1309. MetaFrame *frame;
  1310. Window top_window;
  1311. MetaRectangle rectWorkArea[1];
  1312. MetaRectangle *rectWindow;
  1313. frame = meta_window_get_frame (window);
  1314. if (frame)
  1315. top_window = meta_frame_get_xwindow (frame);
  1316. else
  1317. top_window = meta_window_get_xwindow (window);
  1318. meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
  1319. self = g_object_new (META_TYPE_WINDOW_ACTOR,
  1320. "meta-window", window,
  1321. "x-window", top_window,
  1322. "meta-screen", screen,
  1323. NULL);
  1324. priv = self->priv;
  1325. priv->last_width = -1;
  1326. priv->last_height = -1;
  1327. priv->mapped = meta_window_toplevel_is_mapped (priv->window);
  1328. if (priv->mapped)
  1329. meta_window_actor_queue_create_pixmap (self);
  1330. meta_window_actor_sync_actor_position (self);
  1331. /* Hang our compositor window state off the MetaWindow for fast retrieval */
  1332. meta_window_set_compositor_private (window, G_OBJECT (self));
  1333. if (window->type == META_WINDOW_DROPDOWN_MENU ||
  1334. window->type == META_WINDOW_POPUP_MENU ||
  1335. window->type == META_WINDOW_COMBO) {
  1336. clutter_container_add_actor (CLUTTER_CONTAINER (info->top_window_group),
  1337. CLUTTER_ACTOR (self));
  1338. }
  1339. else if (window->type == META_WINDOW_TOOLTIP) {
  1340. meta_window_get_work_area_all_monitors(window, rectWorkArea);
  1341. rectWindow = meta_window_get_rect(window);
  1342. // move tooltip out of top panel if necessary
  1343. if (rectWindow->y < rectWorkArea->y) {
  1344. meta_window_move(window, FALSE, rectWindow->x, rectWorkArea->y);
  1345. }
  1346. rectWindow = meta_window_get_rect(window);
  1347. // move tooltip out of bottom panel if necessary
  1348. if ((rectWindow->y + rectWindow->height) > (rectWorkArea->y + rectWorkArea->height)) {
  1349. meta_window_move(window, FALSE, rectWindow->x, rectWorkArea->y + rectWorkArea->height - rectWindow->height);
  1350. }
  1351. clutter_container_add_actor (CLUTTER_CONTAINER (info->top_window_group),
  1352. CLUTTER_ACTOR (self));
  1353. }
  1354. else if (window->type == META_WINDOW_DESKTOP) {
  1355. clutter_container_add_actor (CLUTTER_CONTAINER (info->bottom_window_group),
  1356. CLUTTER_ACTOR (self));
  1357. }else{
  1358. clutter_container_add_actor (CLUTTER_CONTAINER (info->window_group),
  1359. CLUTTER_ACTOR (self));
  1360. }
  1361. clutter_actor_hide (CLUTTER_ACTOR (self));
  1362. /* Initial position in the stack is arbitrary; stacking will be synced
  1363. * before we first paint.
  1364. */
  1365. info->windows = g_list_append (info->windows, self);
  1366. return self;
  1367. }
  1368. LOCAL_SYMBOL void
  1369. meta_window_actor_mapped (MetaWindowActor *self)
  1370. {
  1371. MetaWindowActorPrivate *priv = self->priv;
  1372. g_return_if_fail (!priv->mapped);
  1373. priv->mapped = TRUE;
  1374. meta_window_actor_queue_create_pixmap (self);
  1375. }
  1376. LOCAL_SYMBOL void
  1377. meta_window_actor_unmapped (MetaWindowActor *self)
  1378. {
  1379. MetaWindowActorPrivate *priv = self->priv;
  1380. g_return_if_fail (priv->mapped);
  1381. priv->mapped = FALSE;
  1382. if (meta_window_actor_effect_in_progress (self))
  1383. return;
  1384. meta_window_actor_detach (self);
  1385. priv->needs_pixmap = FALSE;
  1386. }
  1387. static void
  1388. meta_window_actor_clear_shape_region (MetaWindowActor *self)
  1389. {
  1390. MetaWindowActorPrivate *priv = self->priv;
  1391. if (priv->shape_region)
  1392. {
  1393. cairo_region_destroy (priv->shape_region);
  1394. priv->shape_region = NULL;
  1395. }
  1396. }
  1397. static void
  1398. meta_window_actor_clear_bounding_region (MetaWindowActor *self)
  1399. {
  1400. MetaWindowActorPrivate *priv = self->priv;
  1401. if (priv->bounding_region)
  1402. {
  1403. cairo_region_destroy (priv->bounding_region);
  1404. priv->bounding_region = NULL;
  1405. }
  1406. }
  1407. static void
  1408. meta_window_actor_clear_shadow_clip (MetaWindowActor *self)
  1409. {
  1410. MetaWindowActorPrivate *priv = self->priv;
  1411. if (priv->shadow_clip)
  1412. {
  1413. cairo_region_destroy (priv->shadow_clip);
  1414. priv->shadow_clip = NULL;
  1415. }
  1416. }
  1417. static void
  1418. meta_window_actor_update_bounding_region_and_borders (MetaWindowActor *self,
  1419. int width,
  1420. int height)
  1421. {
  1422. MetaWindowActorPrivate *priv = self->priv;
  1423. MetaFrameBorders borders;
  1424. cairo_rectangle_int_t bounding_rectangle;
  1425. meta_frame_calc_borders (priv->window->frame, &borders);
  1426. bounding_rectangle.x = borders.invisible.left;
  1427. bounding_rectangle.y = borders.invisible.top;
  1428. width -= borders.invisible.left + borders.invisible.right;
  1429. height -= borders.invisible.top + borders.invisible.bottom;
  1430. bounding_rectangle.width = width;
  1431. bounding_rectangle.height = height;
  1432. if (priv->bounding_region != NULL)
  1433. {
  1434. cairo_rectangle_int_t old_bounding_rectangle;
  1435. cairo_region_get_extents (priv->bounding_region, &old_bounding_rectangle);
  1436. /* Because the bounding region doesn't include the invisible borders,
  1437. * we need to make sure that the border sizes haven't changed before
  1438. * short-circuiting early.
  1439. */
  1440. if (bounding_rectangle.width == old_bounding_rectangle.width &&
  1441. bounding_rectangle.height == old_bounding_rectangle.height &&
  1442. priv->last_borders.invisible.left == borders.invisible.left &&
  1443. priv->last_borders.invisible.right == borders.invisible.right &&
  1444. priv->last_borders.invisible.top == borders.invisible.top &&
  1445. priv->last_borders.invisible.bottom == borders.invisible.bottom)
  1446. return;
  1447. }
  1448. priv->last_borders = borders;
  1449. meta_window_actor_clear_bounding_region (self);
  1450. priv->bounding_region = cairo_region_create_rectangle (&bounding_rectangle);
  1451. meta_window_actor_update_shape (self);
  1452. g_signal_emit (self, signals[SIZE_CHANGED], 0);
  1453. }
  1454. static void
  1455. meta_window_actor_update_shape_region (MetaWindowActor *self,
  1456. cairo_region_t *region)
  1457. {
  1458. MetaWindowActorPrivate *priv = self->priv;
  1459. meta_window_actor_clear_shape_region (self);
  1460. /* region must be non-null */
  1461. priv->shape_region = region;
  1462. cairo_region_reference (region);
  1463. /* Our "shape_region" is called the "bounding region" in the X Shape
  1464. * Extension Documentation.
  1465. *
  1466. * Our "bounding_region" is called the "bounding rectangle", which defines
  1467. * the shape of the window as if it the window was unshaped.
  1468. *
  1469. * The X Shape extension requires that the "bounding region" can never
  1470. * extend outside the "bounding rectangle", and says it must be implicitly
  1471. * clipped before rendering. The region we get back hasn't been clipped.
  1472. * We explicitly clip the region here.
  1473. */
  1474. if (priv->bounding_region != NULL)
  1475. cairo_region_intersect (priv->shape_region, priv->bounding_region);
  1476. }
  1477. /**
  1478. * meta_window_actor_get_obscured_region:
  1479. * @self: a #MetaWindowActor
  1480. *
  1481. * Gets the region that is completely obscured by the window. Coordinates
  1482. * are relative to the upper-left of the window.
  1483. *
  1484. * Return value: (transfer none): the area obscured by the window,
  1485. * %NULL is the same as an empty region.
  1486. */
  1487. LOCAL_SYMBOL cairo_region_t *
  1488. meta_window_actor_get_obscured_region (MetaWindowActor *self)
  1489. {
  1490. MetaWindowActorPrivate *priv = self->priv;
  1491. if (!priv->argb32 && priv->opacity == 0xff && priv->back_pixmap)
  1492. {
  1493. if (priv->shape_region)
  1494. return priv->shape_region;
  1495. else
  1496. return priv->bounding_region;
  1497. }
  1498. else
  1499. return NULL;
  1500. }
  1501. #if 0
  1502. /* Print out a region; useful for debugging */
  1503. static void
  1504. dump_region (cairo_region_t *region)
  1505. {
  1506. int n_rects;
  1507. int i;
  1508. n_rects = cairo_region_num_rectangles (region);
  1509. g_print ("[");
  1510. for (i = 0; i < n_rects; i++)
  1511. {
  1512. cairo_rectangle_int_t rect;
  1513. cairo_region_get_rectangle (region, i, &rect);
  1514. g_print ("+%d+%dx%dx%d ",
  1515. rect.x, rect.y, rect.width, rect.height);
  1516. }
  1517. g_print ("]\n");
  1518. }
  1519. #endif
  1520. /**
  1521. * meta_window_actor_set_visible_region:
  1522. * @self: a #MetaWindowActor
  1523. * @visible_region: the region of the screen that isn't completely
  1524. * obscured.
  1525. *
  1526. * Provides a hint as to what areas of the window need to be
  1527. * drawn. Regions not in @visible_region are completely obscured.
  1528. * This will be set before painting then unset afterwards.
  1529. */
  1530. LOCAL_SYMBOL void
  1531. meta_window_actor_set_visible_region (MetaWindowActor *self,
  1532. cairo_region_t *visible_region)
  1533. {
  1534. MetaWindowActorPrivate *priv = self->priv;
  1535. meta_shaped_texture_set_clip_region (META_SHAPED_TEXTURE (priv->actor),
  1536. visible_region);
  1537. }
  1538. /**
  1539. * meta_window_actor_set_visible_region_beneath:
  1540. * @self: a #MetaWindowActor
  1541. * @visible_region: the region of the screen that isn't completely
  1542. * obscured beneath the main window texture.
  1543. *
  1544. * Provides a hint as to what areas need to be drawn *beneath*
  1545. * the main window texture. This is the relevant visible region
  1546. * when drawing the shadow, properly accounting for areas of the
  1547. * shadow hid by the window itself. This will be set before painting
  1548. * then unset afterwards.
  1549. */
  1550. LOCAL_SYMBOL void
  1551. meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
  1552. cairo_region_t *beneath_region)
  1553. {
  1554. MetaWindowActorPrivate *priv = self->priv;
  1555. gboolean appears_focused = meta_window_appears_focused (priv->window);
  1556. if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
  1557. {
  1558. meta_window_actor_clear_shadow_clip (self);
  1559. priv->shadow_clip = cairo_region_copy (beneath_region);
  1560. if (clip_shadow_under_window (self))
  1561. {
  1562. cairo_region_t *frame_bounds = meta_window_get_frame_bounds (priv->window);
  1563. cairo_region_subtract (priv->shadow_clip, frame_bounds);
  1564. }
  1565. }
  1566. }
  1567. /**
  1568. * meta_window_actor_reset_visible_regions:
  1569. * @self: a #MetaWindowActor
  1570. *
  1571. * Unsets the regions set by meta_window_actor_reset_visible_region() and
  1572. * meta_window_actor_reset_visible_region_beneath()
  1573. */
  1574. LOCAL_SYMBOL void
  1575. meta_window_actor_reset_visible_regions (MetaWindowActor *self)
  1576. {
  1577. MetaWindowActorPrivate *priv = self->priv;
  1578. meta_shaped_texture_set_clip_region (META_SHAPED_TEXTURE (priv->actor),
  1579. NULL);
  1580. meta_window_actor_clear_shadow_clip (self);
  1581. }
  1582. static void
  1583. check_needs_pixmap (MetaWindowActor *self)
  1584. {
  1585. MetaWindowActorPrivate *priv = self->priv;
  1586. MetaScreen *screen = priv->screen;
  1587. MetaDisplay *display = meta_screen_get_display (screen);
  1588. Display *xdisplay = meta_display_get_xdisplay (display);
  1589. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1590. MetaCompositor *compositor;
  1591. Window xwindow = priv->xwindow;
  1592. if (!priv->needs_pixmap)
  1593. return;
  1594. if (!priv->mapped)
  1595. return;
  1596. if (xwindow == meta_screen_get_xroot (screen) ||
  1597. xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
  1598. return;
  1599. compositor = meta_display_get_compositor (display);
  1600. if (priv->size_changed)
  1601. {
  1602. meta_window_actor_detach (self);
  1603. priv->size_changed = FALSE;
  1604. }
  1605. meta_error_trap_push (display);
  1606. if (priv->back_pixmap == None)
  1607. {
  1608. CoglHandle texture;
  1609. meta_error_trap_push (display);
  1610. priv->back_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
  1611. if (meta_error_trap_pop_with_return (display) != Success)
  1612. {
  1613. /* Probably a BadMatch if the window isn't viewable; we could
  1614. * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
  1615. * to avoid this, but there's no reason to take two round trips
  1616. * when one will do. (We need that Sync if we want to handle failures
  1617. * for any reason other than !viewable. That's unlikely, but maybe
  1618. * we'll BadAlloc or something.)
  1619. */
  1620. priv->back_pixmap = None;
  1621. }
  1622. if (priv->back_pixmap == None)
  1623. {
  1624. meta_verbose ("Unable to get named pixmap for %p\n", self);
  1625. meta_window_actor_update_bounding_region_and_borders (self, 0, 0);
  1626. goto out;
  1627. }
  1628. if (compositor->no_mipmaps)
  1629. meta_shaped_texture_set_create_mipmaps (META_SHAPED_TEXTURE (priv->actor),
  1630. FALSE);
  1631. meta_shaped_texture_set_pixmap (META_SHAPED_TEXTURE (priv->actor),
  1632. priv->back_pixmap);
  1633. texture = meta_shaped_texture_get_texture (META_SHAPED_TEXTURE (priv->actor));
  1634. /*
  1635. * This only works *after* actually setting the pixmap, so we have to
  1636. * do it here.
  1637. * See: http://bugzilla.clutter-project.org/show_bug.cgi?id=2236
  1638. */
  1639. if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (texture)))
  1640. g_warning ("NOTE: Not using GLX TFP!\n");
  1641. meta_window_actor_update_bounding_region_and_borders (self,
  1642. cogl_texture_get_width (texture),
  1643. cogl_texture_get_height (texture));
  1644. }
  1645. priv->needs_pixmap = FALSE;
  1646. out:
  1647. meta_error_trap_pop (display);
  1648. }
  1649. static void
  1650. check_needs_shadow (MetaWindowActor *self)
  1651. {
  1652. if (g_getenv ("MUFFIN_NO_SHADOWS")) {
  1653. return;
  1654. }
  1655. MetaWindowActorPrivate *priv = self->priv;
  1656. MetaShadow *old_shadow = NULL;
  1657. MetaShadow **shadow_location;
  1658. gboolean recompute_shadow;
  1659. gboolean should_have_shadow;
  1660. gboolean appears_focused;
  1661. if (!priv->mapped)
  1662. return;
  1663. /* Calling meta_window_actor_has_shadow() here at every pre-paint is cheap
  1664. * and avoids the need to explicitly handle window type changes, which
  1665. * we would do if tried to keep track of when we might be adding or removing
  1666. * a shadow more explicitly. We only keep track of changes to the *shape* of
  1667. * the shadow with priv->recompute_shadow.
  1668. */
  1669. should_have_shadow = meta_window_actor_has_shadow (self);
  1670. appears_focused = meta_window_appears_focused (priv->window);
  1671. if (appears_focused)
  1672. {
  1673. recompute_shadow = priv->recompute_focused_shadow;
  1674. priv->recompute_focused_shadow = FALSE;
  1675. shadow_location = &priv->focused_shadow;
  1676. }
  1677. else
  1678. {
  1679. recompute_shadow = priv->recompute_unfocused_shadow;
  1680. priv->recompute_unfocused_shadow = FALSE;
  1681. shadow_location = &priv->unfocused_shadow;
  1682. }
  1683. if (!should_have_shadow || recompute_shadow)
  1684. {
  1685. if (*shadow_location != NULL)
  1686. {
  1687. old_shadow = *shadow_location;
  1688. *shadow_location = NULL;
  1689. }
  1690. }
  1691. if (*shadow_location == NULL && should_have_shadow)
  1692. {
  1693. if (priv->shadow_shape == NULL)
  1694. {
  1695. if (priv->shape_region)
  1696. priv->shadow_shape = meta_window_shape_new (priv->shape_region);
  1697. else if (priv->bounding_region)
  1698. priv->shadow_shape = meta_window_shape_new (priv->bounding_region);
  1699. }
  1700. if (priv->shadow_shape != NULL)
  1701. {
  1702. MetaShadowFactory *factory = meta_shadow_factory_get_default ();
  1703. const char *shadow_class = meta_window_actor_get_shadow_class (self);
  1704. cairo_rectangle_int_t shape_bounds;
  1705. meta_window_actor_get_shape_bounds (self, &shape_bounds);
  1706. *shadow_location = meta_shadow_factory_get_shadow (factory,
  1707. priv->shadow_shape,
  1708. shape_bounds.width, shape_bounds.height,
  1709. shadow_class, appears_focused);
  1710. }
  1711. }
  1712. if (old_shadow != NULL)
  1713. meta_shadow_unref (old_shadow);
  1714. }
  1715. static gboolean
  1716. is_frozen (MetaWindowActor *self)
  1717. {
  1718. return self->priv->freeze_count ? TRUE : FALSE;
  1719. }
  1720. LOCAL_SYMBOL void
  1721. meta_window_actor_process_damage (MetaWindowActor *self,
  1722. XDamageNotifyEvent *event)
  1723. {
  1724. MetaWindowActorPrivate *priv = self->priv;
  1725. MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
  1726. priv->received_damage = TRUE;
  1727. if (meta_window_is_fullscreen (priv->window) && g_list_last (info->windows)->data == self && !priv->unredirected)
  1728. {
  1729. MetaRectangle window_rect;
  1730. meta_window_get_outer_rect (priv->window, &window_rect);
  1731. if (window_rect.x == event->area.x &&
  1732. window_rect.y == event->area.y &&
  1733. window_rect.width == event->area.width &&
  1734. window_rect.height == event->area.height)
  1735. priv->full_damage_frames_count++;
  1736. else
  1737. priv->full_damage_frames_count = 0;
  1738. if (priv->full_damage_frames_count >= 100)
  1739. priv->does_full_damage = TRUE;
  1740. }
  1741. /* Drop damage event for unredirected windows */
  1742. if (priv->unredirected)
  1743. return;
  1744. if (is_frozen (self))
  1745. {
  1746. /* The window is frozen due to an effect in progress: we ignore damage
  1747. * here on the off chance that this will stop the corresponding
  1748. * texture_from_pixmap from being update.
  1749. *
  1750. * needs_damage_all tracks that some unknown damage happened while the
  1751. * window was frozen so that when the window becomes unfrozen we can
  1752. * issue a full window update to cover any lost damage.
  1753. *
  1754. * It should be noted that this is an unreliable mechanism since it's
  1755. * quite likely that drivers will aim to provide a zero-copy
  1756. * implementation of the texture_from_pixmap extension and in those cases
  1757. * any drawing done to the window is always immediately reflected in the
  1758. * texture regardless of damage event handling.
  1759. */
  1760. priv->needs_damage_all = TRUE;
  1761. return;
  1762. }
  1763. if (!priv->mapped || priv->needs_pixmap)
  1764. return;
  1765. meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor),
  1766. event->area.x,
  1767. event->area.y,
  1768. event->area.width,
  1769. event->area.height);
  1770. }
  1771. LOCAL_SYMBOL void
  1772. meta_window_actor_sync_visibility (MetaWindowActor *self)
  1773. {
  1774. MetaWindowActorPrivate *priv = self->priv;
  1775. if (CLUTTER_ACTOR_IS_VISIBLE (self) != priv->visible)
  1776. {
  1777. if (priv->visible)
  1778. clutter_actor_show (CLUTTER_ACTOR (self));
  1779. else
  1780. clutter_actor_hide (CLUTTER_ACTOR (self));
  1781. }
  1782. }
  1783. static inline void
  1784. set_integral_bounding_rect (cairo_rectangle_int_t *rect,
  1785. double x, double y,
  1786. double width, double height)
  1787. {
  1788. rect->x = floor(x);
  1789. rect->y = floor(y);
  1790. rect->width = ceil(x + width) - rect->x;
  1791. rect->height = ceil(y + height) - rect->y;
  1792. }
  1793. static void
  1794. update_corners (MetaWindowActor *self,
  1795. MetaFrameBorders *borders)
  1796. {
  1797. MetaWindowActorPrivate *priv = self->priv;
  1798. MetaRectangle outer;
  1799. cairo_rectangle_int_t corner_rects[4];
  1800. cairo_region_t *corner_region;
  1801. cairo_path_t *corner_path;
  1802. float top_left, top_right, bottom_left, bottom_right;
  1803. float x, y;
  1804. /* need these to build a path */
  1805. cairo_t *cr;
  1806. cairo_surface_t *surface;
  1807. if (!priv->window->frame)
  1808. {
  1809. meta_shaped_texture_set_overlay_path (META_SHAPED_TEXTURE (priv->actor),
  1810. NULL, NULL);
  1811. return;
  1812. }
  1813. meta_window_get_outer_rect (priv->window, &outer);
  1814. meta_frame_get_corner_radiuses (priv->window->frame,
  1815. &top_left,
  1816. &top_right,
  1817. &bottom_left,
  1818. &bottom_right);
  1819. /* Unfortunately, cairo does not allow us to create a context
  1820. * without a surface. Create a 0x0 image surface to "paint to"
  1821. * so we can get the path. */
  1822. surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
  1823. 0, 0);
  1824. cr = cairo_create (surface);
  1825. /* top left */
  1826. x = borders->invisible.left;
  1827. y = borders->invisible.top;
  1828. set_integral_bounding_rect (&corner_rects[0],
  1829. x, y, top_left, top_left);
  1830. cairo_arc (cr,
  1831. x + top_left,
  1832. y + top_left,
  1833. top_left,
  1834. 0, M_PI*2);
  1835. /* top right */
  1836. x = borders->invisible.left + outer.width - top_right;
  1837. y = borders->invisible.top;
  1838. set_integral_bounding_rect (&corner_rects[1],
  1839. x, y, top_right, top_right);
  1840. cairo_arc (cr,
  1841. x,
  1842. y + top_right,
  1843. top_right,
  1844. 0, M_PI*2);
  1845. /* bottom right */
  1846. x = borders->invisible.left + outer.width - bottom_right;
  1847. y = borders->invisible.top + outer.height - bottom_right;
  1848. set_integral_bounding_rect (&corner_rects[2],
  1849. x, y, bottom_right, bottom_right);
  1850. cairo_arc (cr,
  1851. x,
  1852. y,
  1853. bottom_right,
  1854. 0, M_PI*2);
  1855. /* bottom left */
  1856. x = borders->invisible.left;
  1857. y = borders->invisible.top + outer.height - bottom_left;
  1858. set_integral_bounding_rect (&corner_rects[3],
  1859. x, y, bottom_left, bottom_left);
  1860. cairo_arc (cr,
  1861. x + bottom_left,
  1862. y,
  1863. bottom_left,
  1864. 0, M_PI*2);
  1865. corner_path = cairo_copy_path (cr);
  1866. cairo_surface_destroy (surface);
  1867. cairo_destroy (cr);
  1868. corner_region = cairo_region_create_rectangles (corner_rects, 4);
  1869. meta_shaped_texture_set_overlay_path (META_SHAPED_TEXTURE (priv->actor),
  1870. corner_region, corner_path);
  1871. cairo_region_destroy (corner_region);
  1872. }
  1873. static void
  1874. check_needs_reshape (MetaWindowActor *self)
  1875. {
  1876. MetaWindowActorPrivate *priv = self->priv;
  1877. MetaScreen *screen = priv->screen;
  1878. MetaDisplay *display = meta_screen_get_display (screen);
  1879. MetaFrameBorders borders;
  1880. cairo_region_t *region;
  1881. if (!priv->needs_reshape)
  1882. return;
  1883. meta_shaped_texture_set_shape_region (META_SHAPED_TEXTURE (priv->actor), NULL);
  1884. meta_window_actor_clear_shape_region (self);
  1885. meta_frame_calc_borders (priv->window->frame, &borders);
  1886. region = meta_window_get_frame_bounds (priv->window);
  1887. if (region != NULL)
  1888. {
  1889. /* This returns the window's internal frame bounds region,
  1890. * so we need to copy it because we modify it below. */
  1891. region = cairo_region_copy (region);
  1892. }
  1893. else
  1894. {
  1895. /* If we have no region, we have no frame. We have no frame,
  1896. * so just use the bounding region instead */
  1897. region = cairo_region_copy (priv->bounding_region);
  1898. }
  1899. #ifdef HAVE_SHAPE
  1900. if (priv->window->has_shape)
  1901. {
  1902. Display *xdisplay = meta_display_get_xdisplay (display);
  1903. XRectangle *rects;
  1904. int n_rects, ordering;
  1905. cairo_rectangle_int_t client_area;
  1906. client_area.width = priv->window->rect.width;
  1907. client_area.height = priv->window->rect.height;
  1908. if (priv->window->frame)
  1909. {
  1910. client_area.x = borders.total.left;
  1911. client_area.y = borders.total.top;
  1912. }
  1913. else
  1914. {
  1915. client_area.x = 0;
  1916. client_area.y = 0;
  1917. }
  1918. /* Punch out client area. */
  1919. cairo_region_subtract_rectangle (region, &client_area);
  1920. meta_error_trap_push (display);
  1921. rects = XShapeGetRectangles (xdisplay,
  1922. priv->window->xwindow,
  1923. ShapeBounding,
  1924. &n_rects,
  1925. &ordering);
  1926. meta_error_trap_pop (display);
  1927. if (rects)
  1928. {
  1929. int i;
  1930. for (i = 0; i < n_rects; i ++)
  1931. {
  1932. cairo_rectangle_int_t rect = { rects[i].x + client_area.x,
  1933. rects[i].y + client_area.y,
  1934. rects[i].width,
  1935. rects[i].height };
  1936. cairo_region_union_rectangle (region, &rect);
  1937. }
  1938. XFree (rects);
  1939. }
  1940. }
  1941. #endif
  1942. meta_shaped_texture_set_shape_region (META_SHAPED_TEXTURE (priv->actor),
  1943. region);
  1944. meta_window_actor_update_shape_region (self, region);
  1945. cairo_region_destroy (region);
  1946. update_corners (self, &borders);
  1947. priv->needs_reshape = FALSE;
  1948. meta_window_actor_invalidate_shadow (self);
  1949. }
  1950. LOCAL_SYMBOL void
  1951. meta_window_actor_update_shape (MetaWindowActor *self)
  1952. {
  1953. MetaWindowActorPrivate *priv = self->priv;
  1954. priv->needs_reshape = TRUE;
  1955. if (priv->shadow_shape != NULL)
  1956. {
  1957. meta_window_shape_unref (priv->shadow_shape);
  1958. priv->shadow_shape = NULL;
  1959. }
  1960. clutter_actor_queue_redraw (priv->actor);
  1961. }
  1962. LOCAL_SYMBOL void
  1963. meta_window_actor_pre_paint (MetaWindowActor *self)
  1964. {
  1965. MetaWindowActorPrivate *priv = self->priv;
  1966. MetaScreen *screen = priv->screen;
  1967. MetaDisplay *display = meta_screen_get_display (screen);
  1968. Display *xdisplay = meta_display_get_xdisplay (display);
  1969. if (is_frozen (self))
  1970. {
  1971. /* The window is frozen due to a pending animation: we'll wait until
  1972. * the animation finishes to reshape and repair the window */
  1973. return;
  1974. }
  1975. if (priv->unredirected)
  1976. {
  1977. /* Nothing to do here until/if the window gets redirected again */
  1978. return;
  1979. }
  1980. if (priv->received_damage)
  1981. {
  1982. meta_error_trap_push (display);
  1983. XDamageSubtract (xdisplay, priv->damage, None, None);
  1984. meta_error_trap_pop (display);
  1985. /* We need to make sure that any X drawing that happens before the
  1986. * XDamageSubtract() above is visible to subsequent GL rendering;
  1987. * the only standardized way to do this is EXT_x11_sync_object,
  1988. * which isn't yet widely available. For now, we count on details
  1989. * of Xorg and the open source drivers, and hope for the best
  1990. * otherwise.
  1991. *
  1992. * Xorg and open source driver specifics:
  1993. *
  1994. * The X server makes sure to flush drawing to the kernel before
  1995. * sending out damage events, but since we use DamageReportBoundingBox
  1996. * there may be drawing between the last damage event and the
  1997. * XDamageSubtract() that needs to be flushed as well.
  1998. *
  1999. * Xorg always makes sure that drawing is flushed to the kernel
  2000. * before writing events or responses to the client, so any round trip
  2001. * request at this point is sufficient to flush the GLX buffers.
  2002. */
  2003. XSync (xdisplay, False);
  2004. priv->received_damage = FALSE;
  2005. }
  2006. check_needs_pixmap (self);
  2007. check_needs_reshape (self);
  2008. check_needs_shadow (self);
  2009. }
  2010. LOCAL_SYMBOL void
  2011. meta_window_actor_invalidate_shadow (MetaWindowActor *self)
  2012. {
  2013. MetaWindowActorPrivate *priv = self->priv;
  2014. priv->recompute_focused_shadow = TRUE;
  2015. priv->recompute_unfocused_shadow = TRUE;
  2016. clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
  2017. }
  2018. LOCAL_SYMBOL void
  2019. meta_window_actor_update_opacity (MetaWindowActor *self)
  2020. {
  2021. MetaWindowActorPrivate *priv = self->priv;
  2022. MetaDisplay *display = meta_screen_get_display (priv->screen);
  2023. MetaCompositor *compositor = meta_display_get_compositor (display);
  2024. Window xwin = meta_window_get_xwindow (priv->window);
  2025. gulong value;
  2026. guint8 opacity;
  2027. if (meta_prop_get_cardinal (display, xwin,
  2028. compositor->atom_net_wm_window_opacity,
  2029. &value))
  2030. {
  2031. opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff));
  2032. }
  2033. else
  2034. opacity = 255;
  2035. self->priv->opacity = opacity;
  2036. clutter_actor_set_opacity (self->priv->actor, opacity);
  2037. }