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.
 
 
 
 

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