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.
 
 
 
 

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