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.
 
 
 
 

1686 lines
51 KiB

  1. /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2. /**
  3. * SECTION:compositor
  4. * @title: MetaCompositor
  5. * @short_Description: Compositor API
  6. *
  7. * At a high-level, a window is not-visible or visible. When a
  8. * window is added (with meta_compositor_add_window()) it is not visible.
  9. * meta_compositor_show_window() indicates a transition from not-visible to
  10. * visible. Some of the reasons for this:
  11. *
  12. * - Window newly created
  13. * - Window is unminimized
  14. * - Window is moved to the current desktop
  15. * - Window was made sticky
  16. *
  17. * meta_compositor_hide_window() indicates that the window has transitioned from
  18. * visible to not-visible. Some reasons include:
  19. *
  20. * - Window was destroyed
  21. * - Window is minimized
  22. * - Window is moved to a different desktop
  23. * - Window no longer sticky.
  24. *
  25. * Note that combinations are possible - a window might have first
  26. * been minimized and then moved to a different desktop. The 'effect' parameter
  27. * to meta_compositor_show_window() and meta_compositor_hide_window() is a hint
  28. * as to the appropriate effect to show the user and should not
  29. * be considered to be indicative of a state change.
  30. *
  31. * When the active workspace is changed, meta_compositor_switch_workspace() is
  32. * called first, then meta_compositor_show_window() and
  33. * meta_compositor_hide_window() are called individually for each window
  34. * affected, with an effect of META_COMP_EFFECT_NONE.
  35. * If hiding windows will affect the switch workspace animation, the
  36. * compositor needs to delay hiding the windows until the switch
  37. * workspace animation completes.
  38. *
  39. * meta_compositor_maximize_window() and meta_compositor_unmaximize_window()
  40. * are transitions within the visible state. The window is resized __before__
  41. * the call, so it may be necessary to readjust the display based on the
  42. * old_rect to start the animation.
  43. *
  44. * # Containers #
  45. *
  46. * There's two containers in the stage that are used to place window actors, here
  47. * are listed in the order in which they are painted:
  48. *
  49. * - window group, accessible with meta_get_window_group_for_screen()
  50. * - top window group, accessible with meta_get_top_window_group_for_screen()
  51. *
  52. * Muffin will place actors representing windows in the window group, except for
  53. * override-redirect windows (ie. popups and menus) which will be placed in the
  54. * top window group.
  55. */
  56. #include <config.h>
  57. #include <clutter/x11/clutter-x11.h>
  58. #include <meta/screen.h>
  59. #include <meta/errors.h>
  60. #include <meta/window.h>
  61. #include "compositor-private.h"
  62. #include <meta/compositor-muffin.h>
  63. #include "xprops.h"
  64. #include <meta/prefs.h>
  65. #include <meta/main.h>
  66. #include <meta/meta-shadow-factory.h>
  67. #include "meta-window-actor-private.h"
  68. #include "meta-window-group.h"
  69. #include "meta-background-actor-private.h"
  70. #include "window-private.h" /* to check window->hidden */
  71. #include "display-private.h" /* for meta_display_lookup_x_window() */
  72. #include <X11/extensions/shape.h>
  73. #include <X11/extensions/Xcomposite.h>
  74. #include "meta-sync-ring.h"
  75. /* #define DEBUG_TRACE g_print */
  76. #define DEBUG_TRACE(X)
  77. static inline gboolean
  78. composite_at_least_version (MetaDisplay *display, int maj, int min)
  79. {
  80. static int major = -1;
  81. static int minor = -1;
  82. if (major == -1)
  83. meta_display_get_compositor_version (display, &major, &minor);
  84. return (major > maj || (major == maj && minor >= min));
  85. }
  86. static void sync_actor_stacking (MetaCompScreen *info);
  87. static void
  88. meta_finish_workspace_switch (MetaCompScreen *info)
  89. {
  90. GList *l;
  91. /* Finish hiding and showing actors for the new workspace */
  92. for (l = info->windows; l; l = l->next)
  93. meta_window_actor_sync_visibility (l->data);
  94. /*
  95. * Fix up stacking order in case the plugin messed it up.
  96. */
  97. sync_actor_stacking (info);
  98. /* printf ("... FINISHED DESKTOP SWITCH\n"); */
  99. }
  100. LOCAL_SYMBOL void
  101. meta_switch_workspace_completed (MetaScreen *screen)
  102. {
  103. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  104. /* FIXME -- must redo stacking order */
  105. info->switch_workspace_in_progress--;
  106. if (info->switch_workspace_in_progress < 0)
  107. {
  108. g_warning ("Error in workspace_switch accounting!");
  109. info->switch_workspace_in_progress = 0;
  110. }
  111. if (!info->switch_workspace_in_progress)
  112. meta_finish_workspace_switch (info);
  113. }
  114. void
  115. meta_compositor_destroy (MetaCompositor *compositor)
  116. {
  117. clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
  118. clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
  119. if (compositor->have_x11_sync_object)
  120. meta_sync_ring_destroy ();
  121. }
  122. static void
  123. add_win (MetaWindow *window)
  124. {
  125. MetaScreen *screen = meta_window_get_screen (window);
  126. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  127. g_return_if_fail (info != NULL);
  128. meta_window_actor_new (window);
  129. sync_actor_stacking (info);
  130. }
  131. static void
  132. process_damage (MetaCompositor *compositor,
  133. XDamageNotifyEvent *event,
  134. MetaWindow *window)
  135. {
  136. MetaWindowActor *window_actor;
  137. if (window == NULL)
  138. return;
  139. window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  140. if (window_actor == NULL)
  141. return;
  142. meta_window_actor_process_damage (window_actor, event);
  143. compositor->frame_has_updated_xsurfaces = TRUE;
  144. }
  145. static void
  146. process_property_notify (MetaCompositor *compositor,
  147. XPropertyEvent *event,
  148. MetaWindow *window)
  149. {
  150. MetaWindowActor *window_actor;
  151. if (event->atom == compositor->atom_x_root_pixmap)
  152. {
  153. GSList *l;
  154. for (l = meta_display_get_screens (compositor->display); l; l = l->next)
  155. {
  156. MetaScreen *screen = l->data;
  157. if (event->window == meta_screen_get_xroot (screen))
  158. {
  159. meta_background_actor_update (screen);
  160. return;
  161. }
  162. }
  163. }
  164. if (window == NULL)
  165. return;
  166. window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  167. if (window_actor == NULL)
  168. return;
  169. /* Check for the opacity changing */
  170. if (event->atom == compositor->atom_net_wm_window_opacity)
  171. {
  172. meta_window_actor_update_opacity (window_actor);
  173. DEBUG_TRACE ("process_property_notify: net_wm_window_opacity\n");
  174. return;
  175. }
  176. DEBUG_TRACE ("process_property_notify: unknown\n");
  177. }
  178. static Window
  179. get_output_window (MetaScreen *screen)
  180. {
  181. MetaDisplay *display = meta_screen_get_display (screen);
  182. Display *xdisplay = meta_display_get_xdisplay (display);
  183. Window output, xroot;
  184. XWindowAttributes attr;
  185. long event_mask;
  186. xroot = meta_screen_get_xroot (screen);
  187. event_mask = FocusChangeMask |
  188. ExposureMask |
  189. EnterWindowMask | LeaveWindowMask |
  190. PointerMotionMask |
  191. PropertyChangeMask |
  192. ButtonPressMask | ButtonReleaseMask |
  193. KeyPressMask | KeyReleaseMask;
  194. output = XCompositeGetOverlayWindow (xdisplay, xroot);
  195. if (XGetWindowAttributes (xdisplay, output, &attr))
  196. {
  197. event_mask |= attr.your_event_mask;
  198. }
  199. XSelectInput (xdisplay, output, event_mask);
  200. return output;
  201. }
  202. /**
  203. * meta_get_stage_for_screen:
  204. * @screen: a #MetaScreen
  205. *
  206. * Returns: (transfer none): The #ClutterStage for the screen
  207. */
  208. ClutterActor *
  209. meta_get_stage_for_screen (MetaScreen *screen)
  210. {
  211. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  212. if (!info)
  213. return NULL;
  214. return info->stage;
  215. }
  216. /**
  217. * meta_get_overlay_group_for_screen:
  218. * @screen: a #MetaScreen
  219. *
  220. * Returns: (transfer none): The overlay group corresponding to @screen
  221. */
  222. ClutterActor *
  223. meta_get_overlay_group_for_screen (MetaScreen *screen)
  224. {
  225. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  226. if (!info)
  227. return NULL;
  228. return info->overlay_group;
  229. }
  230. /**
  231. * meta_get_window_group_for_screen:
  232. * @screen: a #MetaScreen
  233. *
  234. * Returns: (transfer none): The window group corresponding to @screen
  235. */
  236. ClutterActor *
  237. meta_get_window_group_for_screen (MetaScreen *screen)
  238. {
  239. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  240. if (!info)
  241. return NULL;
  242. return info->window_group;
  243. }
  244. /**
  245. * meta_get_bottom_window_group_for_screen:
  246. * @screen: a #MetaScreen
  247. *
  248. * Returns: (transfer none): The bottom window group corresponding to @screen
  249. */
  250. ClutterActor *
  251. meta_get_bottom_window_group_for_screen (MetaScreen *screen)
  252. {
  253. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  254. if (!info)
  255. return NULL;
  256. return info->bottom_window_group;
  257. }
  258. /**
  259. * meta_get_top_window_group_for_screen:
  260. * @screen: a #MetaScreen
  261. *
  262. * Returns: (transfer none): The top window group corresponding to @screen
  263. */
  264. ClutterActor *
  265. meta_get_top_window_group_for_screen (MetaScreen *screen)
  266. {
  267. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  268. if (!info)
  269. return NULL;
  270. return info->top_window_group;
  271. }
  272. /**
  273. * meta_get_background_actor_for_screen:
  274. * @screen: a #MetaScreen
  275. *
  276. * Gets the actor that draws the root window background under the windows.
  277. * The root window background automatically tracks the image or color set
  278. * by the environment.
  279. *
  280. * Returns: (transfer none): The background actor corresponding to @screen
  281. */
  282. ClutterActor *
  283. meta_get_background_actor_for_screen (MetaScreen *screen)
  284. {
  285. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  286. if (!info)
  287. return NULL;
  288. return info->background_actor;
  289. }
  290. /**
  291. * meta_get_window_actors:
  292. * @screen: a #MetaScreen
  293. *
  294. * Returns: (transfer none) (element-type Clutter.Actor): The set of #MetaWindowActor on @screen
  295. */
  296. GList *
  297. meta_get_window_actors (MetaScreen *screen)
  298. {
  299. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  300. if (!info)
  301. return NULL;
  302. return info->windows;
  303. }
  304. static void
  305. do_set_stage_input_region (MetaScreen *screen,
  306. XserverRegion region)
  307. {
  308. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  309. MetaDisplay *display = meta_screen_get_display (screen);
  310. Display *xdpy = meta_display_get_xdisplay (display);
  311. Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
  312. XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
  313. /* It's generally a good heuristic that when a crossing event is generated because
  314. * we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
  315. * it's not the user doing something, it's the environment changing under the user.
  316. */
  317. meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
  318. XFixesSetWindowShapeRegion (xdpy, info->output, ShapeInput, 0, 0, region);
  319. }
  320. void
  321. meta_set_stage_input_region (MetaScreen *screen,
  322. XserverRegion region)
  323. {
  324. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  325. MetaDisplay *display = meta_screen_get_display (screen);
  326. Display *xdpy = meta_display_get_xdisplay (display);
  327. if (info->stage && info->output)
  328. {
  329. do_set_stage_input_region (screen, region);
  330. }
  331. else
  332. {
  333. /* Reset info->pending_input_region if one existed before and set the new
  334. * one to use it later. */
  335. if (info->pending_input_region)
  336. {
  337. XFixesDestroyRegion (xdpy, info->pending_input_region);
  338. info->pending_input_region = None;
  339. }
  340. if (region != None)
  341. {
  342. info->pending_input_region = XFixesCreateRegion (xdpy, NULL, 0);
  343. XFixesCopyRegion (xdpy, info->pending_input_region, region);
  344. }
  345. }
  346. }
  347. void
  348. meta_empty_stage_input_region (MetaScreen *screen)
  349. {
  350. /* Using a static region here is a bit hacky, but Metacity never opens more than
  351. * one XDisplay, so it works fine. */
  352. static XserverRegion region = None;
  353. if (region == None)
  354. {
  355. MetaDisplay *display = meta_screen_get_display (screen);
  356. Display *xdpy = meta_display_get_xdisplay (display);
  357. region = XFixesCreateRegion (xdpy, NULL, 0);
  358. }
  359. meta_set_stage_input_region (screen, region);
  360. }
  361. LOCAL_SYMBOL gboolean
  362. meta_begin_modal_for_plugin (MetaScreen *screen,
  363. MetaPlugin *plugin,
  364. Window grab_window,
  365. Cursor cursor,
  366. MetaModalOptions options,
  367. guint32 timestamp)
  368. {
  369. /* To some extent this duplicates code in meta_display_begin_grab_op(), but there
  370. * are significant differences in how we handle grabs that make it difficult to
  371. * merge the two.
  372. */
  373. MetaDisplay *display = meta_screen_get_display (screen);
  374. Display *xdpy = meta_display_get_xdisplay (display);
  375. MetaCompositor *compositor = display->compositor;
  376. gboolean pointer_grabbed = FALSE;
  377. int result;
  378. if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
  379. return FALSE;
  380. if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
  381. {
  382. result = XGrabPointer (xdpy, grab_window,
  383. False, /* owner_events */
  384. (ButtonPressMask | ButtonReleaseMask |
  385. EnterWindowMask | LeaveWindowMask | PointerMotionMask),
  386. GrabModeAsync, GrabModeAsync,
  387. None, /* confine to */
  388. cursor,
  389. timestamp);
  390. if (result != Success)
  391. goto fail;
  392. pointer_grabbed = TRUE;
  393. }
  394. if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
  395. {
  396. result = XGrabKeyboard (xdpy, grab_window,
  397. False, /* owner_events */
  398. GrabModeAsync, GrabModeAsync,
  399. timestamp);
  400. if (result != Success)
  401. goto fail;
  402. }
  403. display->grab_op = META_GRAB_OP_COMPOSITOR;
  404. display->grab_window = NULL;
  405. display->grab_screen = screen;
  406. display->grab_have_pointer = TRUE;
  407. display->grab_have_keyboard = TRUE;
  408. compositor->modal_plugin = plugin;
  409. return TRUE;
  410. fail:
  411. if (pointer_grabbed)
  412. XUngrabPointer (xdpy, timestamp);
  413. return FALSE;
  414. }
  415. LOCAL_SYMBOL void
  416. meta_end_modal_for_plugin (MetaScreen *screen,
  417. MetaPlugin *plugin,
  418. guint32 timestamp)
  419. {
  420. MetaDisplay *display = meta_screen_get_display (screen);
  421. Display *xdpy = meta_display_get_xdisplay (display);
  422. MetaCompositor *compositor = display->compositor;
  423. g_return_if_fail (compositor->modal_plugin == plugin);
  424. XUngrabPointer (xdpy, timestamp);
  425. XUngrabKeyboard (xdpy, timestamp);
  426. display->grab_op = META_GRAB_OP_NONE;
  427. display->grab_window = NULL;
  428. display->grab_screen = NULL;
  429. display->grab_have_pointer = FALSE;
  430. display->grab_have_keyboard = FALSE;
  431. compositor->modal_plugin = NULL;
  432. }
  433. /* This is used when reloading plugins to make sure we don't have
  434. * a left-over modal grab for this screen.
  435. */
  436. LOCAL_SYMBOL void
  437. meta_check_end_modal (MetaScreen *screen)
  438. {
  439. MetaDisplay *display = meta_screen_get_display (screen);
  440. MetaCompositor *compositor = display->compositor;
  441. if (compositor->modal_plugin &&
  442. meta_plugin_get_screen (compositor->modal_plugin) == screen)
  443. {
  444. meta_end_modal_for_plugin (screen,
  445. compositor->modal_plugin,
  446. CurrentTime);
  447. }
  448. }
  449. static void
  450. after_stage_paint (ClutterStage *stage,
  451. gpointer data)
  452. {
  453. MetaCompScreen *info = (MetaCompScreen*) data;
  454. GList *l;
  455. for (l = info->windows; l; l = l->next)
  456. meta_window_actor_post_paint (l->data);
  457. }
  458. void
  459. meta_compositor_manage_screen (MetaCompositor *compositor,
  460. MetaScreen *screen)
  461. {
  462. MetaCompScreen *info;
  463. MetaDisplay *display = meta_screen_get_display (screen);
  464. Display *xdisplay = meta_display_get_xdisplay (display);
  465. int screen_number = meta_screen_get_screen_number (screen);
  466. Window xroot = meta_screen_get_xroot (screen);
  467. Window xwin;
  468. gint width, height;
  469. XWindowAttributes attr;
  470. long event_mask;
  471. guint n_retries;
  472. guint max_retries;
  473. /* Check if the screen is already managed */
  474. if (meta_screen_get_compositor_data (screen))
  475. return;
  476. if (meta_get_replace_current_wm ())
  477. max_retries = 5;
  478. else
  479. max_retries = 1;
  480. n_retries = 0;
  481. /* Some compositors (like old versions of Muffin) might not properly unredirect
  482. * subwindows before destroying the WM selection window; so we wait a while
  483. * for such a compositor to exit before giving up.
  484. */
  485. while (TRUE)
  486. {
  487. meta_error_trap_push_with_return (display);
  488. XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
  489. XSync (xdisplay, FALSE);
  490. if (!meta_error_trap_pop_with_return (display))
  491. break;
  492. if (n_retries == max_retries)
  493. {
  494. /* This probably means that a non-WM compositor like xcompmgr is running;
  495. * we have no way to get it to exit */
  496. meta_fatal (_("Another compositing manager is already running on screen %i on display \"%s\"."),
  497. screen_number, display->name);
  498. }
  499. n_retries++;
  500. g_usleep (G_USEC_PER_SEC);
  501. }
  502. info = g_new0 (MetaCompScreen, 1);
  503. /*
  504. * We use an empty input region for Clutter as a default because that allows
  505. * the user to interact with all the windows displayed on the screen.
  506. * We have to initialize info->pending_input_region to an empty region explicitly,
  507. * because None value is used to mean that the whole screen is an input region.
  508. */
  509. info->pending_input_region = XFixesCreateRegion (xdisplay, NULL, 0);
  510. info->screen = screen;
  511. meta_screen_set_compositor_data (screen, info);
  512. info->output = None;
  513. info->windows = NULL;
  514. meta_screen_set_cm_selection (screen);
  515. info->stage = clutter_stage_new ();
  516. #if CLUTTER_CHECK_VERSION (1, 19, 5) /* Unstable API change */
  517. g_signal_connect_after (CLUTTER_STAGE (info->stage), "after-paint",
  518. G_CALLBACK (after_stage_paint), info);
  519. #else
  520. clutter_stage_set_paint_callback (CLUTTER_STAGE (info->stage),
  521. after_stage_paint,
  522. info,
  523. NULL);
  524. #endif
  525. clutter_stage_set_sync_delay (CLUTTER_STAGE (info->stage), META_SYNC_DELAY);
  526. meta_screen_get_size (screen, &width, &height);
  527. clutter_actor_realize (info->stage);
  528. xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
  529. XResizeWindow (xdisplay, xwin, width, height);
  530. event_mask = FocusChangeMask |
  531. ExposureMask |
  532. EnterWindowMask | LeaveWindowMask |
  533. PointerMotionMask |
  534. PropertyChangeMask |
  535. ButtonPressMask | ButtonReleaseMask |
  536. KeyPressMask | KeyReleaseMask |
  537. StructureNotifyMask;
  538. if (XGetWindowAttributes (xdisplay, xwin, &attr))
  539. {
  540. event_mask |= attr.your_event_mask;
  541. }
  542. XSelectInput (xdisplay, xwin, event_mask);
  543. info->window_group = meta_window_group_new (screen);
  544. info->background_actor = meta_background_actor_new_for_screen (screen);
  545. info->bottom_window_group = clutter_group_new();
  546. info->overlay_group = clutter_group_new ();
  547. info->top_window_group = meta_window_group_new (screen);
  548. info->hidden_group = clutter_group_new ();
  549. clutter_container_add (CLUTTER_CONTAINER (info->window_group),
  550. info->background_actor,
  551. NULL);
  552. clutter_container_add (CLUTTER_CONTAINER (info->stage),
  553. info->window_group,
  554. info->top_window_group,
  555. info->overlay_group,
  556. info->hidden_group,
  557. NULL);
  558. clutter_actor_hide (info->hidden_group);
  559. info->plugin_mgr = meta_plugin_manager_new (screen);
  560. /*
  561. * Delay the creation of the overlay window as long as we can, to avoid
  562. * blanking out the screen. This means that during the plugin loading, the
  563. * overlay window is not accessible; if the plugin needs to access it
  564. * directly, it should hook into the "show" signal on stage, and do
  565. * its stuff there.
  566. */
  567. info->output = get_output_window (screen);
  568. XReparentWindow (xdisplay, xwin, info->output, 0, 0);
  569. /* Make sure there isn't any left-over output shape on the
  570. * overlay window by setting the whole screen to be an
  571. * output region.
  572. *
  573. * Note: there doesn't seem to be any real chance of that
  574. * because the X server will destroy the overlay window
  575. * when the last client using it exits.
  576. */
  577. XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
  578. do_set_stage_input_region (screen, info->pending_input_region);
  579. if (info->pending_input_region != None)
  580. {
  581. XFixesDestroyRegion (xdisplay, info->pending_input_region);
  582. info->pending_input_region = None;
  583. }
  584. clutter_actor_show (info->overlay_group);
  585. clutter_actor_show (info->stage);
  586. compositor->have_x11_sync_object = meta_sync_ring_init (xdisplay);
  587. }
  588. void
  589. meta_compositor_unmanage_screen (MetaCompositor *compositor,
  590. MetaScreen *screen)
  591. {
  592. MetaDisplay *display = meta_screen_get_display (screen);
  593. Display *xdisplay = meta_display_get_xdisplay (display);
  594. Window xroot = meta_screen_get_xroot (screen);
  595. /* This is the most important part of cleanup - we have to do this
  596. * before giving up the window manager selection or the next
  597. * window manager won't be able to redirect subwindows */
  598. XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
  599. }
  600. /*
  601. * Shapes the cow so that the given window is exposed,
  602. * when metaWindow is NULL it clears the shape again
  603. */
  604. static void
  605. meta_shape_cow_for_window (MetaScreen *screen,
  606. MetaWindow *metaWindow)
  607. {
  608. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  609. Display *xdisplay = meta_display_get_xdisplay (meta_screen_get_display (screen));
  610. if (metaWindow == NULL)
  611. XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
  612. else
  613. {
  614. XserverRegion output_region;
  615. XRectangle screen_rect, window_bounds;
  616. int width, height;
  617. MetaRectangle rect;
  618. meta_window_get_outer_rect (metaWindow, &rect);
  619. window_bounds.x = rect.x;
  620. window_bounds.y = rect.y;
  621. window_bounds.width = rect.width;
  622. window_bounds.height = rect.height;
  623. meta_screen_get_size (screen, &width, &height);
  624. screen_rect.x = 0;
  625. screen_rect.y = 0;
  626. screen_rect.width = width;
  627. screen_rect.height = height;
  628. output_region = XFixesCreateRegion (xdisplay, &window_bounds, 1);
  629. XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region);
  630. XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, output_region);
  631. XFixesDestroyRegion (xdisplay, output_region);
  632. }
  633. }
  634. void
  635. meta_compositor_add_window (MetaCompositor *compositor,
  636. MetaWindow *window)
  637. {
  638. MetaScreen *screen = meta_window_get_screen (window);
  639. MetaDisplay *display = meta_screen_get_display (screen);
  640. DEBUG_TRACE ("meta_compositor_add_window\n");
  641. meta_error_trap_push (display);
  642. add_win (window);
  643. meta_error_trap_pop (display);
  644. }
  645. void
  646. meta_compositor_remove_window (MetaCompositor *compositor,
  647. MetaWindow *window)
  648. {
  649. MetaWindowActor *window_actor = NULL;
  650. MetaScreen *screen;
  651. MetaCompScreen *info;
  652. DEBUG_TRACE ("meta_compositor_remove_window\n");
  653. window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  654. if (!window_actor)
  655. return;
  656. screen = meta_window_get_screen (window);
  657. info = meta_screen_get_compositor_data (screen);
  658. if (window_actor == info->unredirected_window)
  659. {
  660. meta_window_actor_set_redirected (window_actor, TRUE);
  661. meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
  662. NULL);
  663. info->unredirected_window = NULL;
  664. }
  665. meta_window_actor_destroy (window_actor);
  666. }
  667. void
  668. meta_compositor_set_updates_frozen (MetaCompositor *compositor,
  669. MetaWindow *window,
  670. gboolean updates_frozen)
  671. {
  672. MetaWindowActor *window_actor;
  673. DEBUG_TRACE ("meta_compositor_set_updates_frozen\n");
  674. window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  675. if (!window_actor)
  676. return;
  677. meta_window_actor_set_updates_frozen (window_actor, updates_frozen);
  678. }
  679. void
  680. meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
  681. MetaWindow *window,
  682. gboolean no_delay_frame)
  683. {
  684. MetaWindowActor *window_actor;
  685. DEBUG_TRACE ("meta_compositor_queue_frame_drawn\n");
  686. window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  687. if (!window_actor)
  688. return;
  689. meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame);
  690. }
  691. static gboolean
  692. is_grabbed_event (XEvent *event)
  693. {
  694. switch (event->xany.type)
  695. {
  696. case ButtonPress:
  697. case ButtonRelease:
  698. case EnterNotify:
  699. case LeaveNotify:
  700. case MotionNotify:
  701. case KeyPress:
  702. case KeyRelease:
  703. return TRUE;
  704. }
  705. return FALSE;
  706. }
  707. void
  708. meta_compositor_window_shape_changed (MetaCompositor *compositor,
  709. MetaWindow *window)
  710. {
  711. MetaWindowActor *window_actor;
  712. window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  713. meta_window_actor_update_shape (window_actor);
  714. }
  715. /**
  716. * meta_compositor_process_event: (skip)
  717. *
  718. */
  719. gboolean
  720. meta_compositor_process_event (MetaCompositor *compositor,
  721. XEvent *event,
  722. MetaWindow *window)
  723. {
  724. if (compositor->modal_plugin && is_grabbed_event (event))
  725. {
  726. MetaPluginClass *klass = META_PLUGIN_GET_CLASS (compositor->modal_plugin);
  727. if (klass->xevent_filter)
  728. klass->xevent_filter (compositor->modal_plugin, event);
  729. /* We always consume events even if the plugin says it didn't handle them;
  730. * exclusive is exclusive */
  731. return TRUE;
  732. }
  733. if (window)
  734. {
  735. MetaCompScreen *info;
  736. MetaScreen *screen;
  737. screen = meta_window_get_screen (window);
  738. info = meta_screen_get_compositor_data (screen);
  739. if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
  740. {
  741. DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
  742. return TRUE;
  743. }
  744. }
  745. else
  746. {
  747. GSList *l;
  748. l = meta_display_get_screens (compositor->display);
  749. while (l)
  750. {
  751. MetaScreen *screen = l->data;
  752. MetaCompScreen *info;
  753. info = meta_screen_get_compositor_data (screen);
  754. if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
  755. {
  756. DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
  757. return TRUE;
  758. }
  759. l = l->next;
  760. }
  761. }
  762. switch (event->type)
  763. {
  764. case PropertyNotify:
  765. process_property_notify (compositor, (XPropertyEvent *) event, window);
  766. break;
  767. default:
  768. if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
  769. {
  770. /* Core code doesn't handle damage events, so we need to extract the MetaWindow
  771. * ourselves
  772. */
  773. if (window == NULL)
  774. {
  775. Window xwin = ((XDamageNotifyEvent *) event)->drawable;
  776. window = meta_display_lookup_x_window (compositor->display, xwin);
  777. }
  778. DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
  779. process_damage (compositor, (XDamageNotifyEvent *) event, window);
  780. }
  781. break;
  782. }
  783. if (compositor->have_x11_sync_object)
  784. meta_sync_ring_handle_event (event);
  785. /* Clutter needs to know about MapNotify events otherwise it will
  786. think the stage is invisible */
  787. if (event->type == MapNotify)
  788. clutter_x11_handle_event (event);
  789. /* The above handling is basically just "observing" the events, so we return
  790. * FALSE to indicate that the event should not be filtered out; if we have
  791. * GTK+ windows in the same process, GTK+ needs the ConfigureNotify event, for example.
  792. */
  793. return FALSE;
  794. }
  795. void
  796. meta_compositor_show_window (MetaCompositor *compositor,
  797. MetaWindow *window,
  798. MetaCompEffect effect)
  799. {
  800. MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  801. DEBUG_TRACE ("meta_compositor_show_window\n");
  802. if (!window_actor)
  803. return;
  804. meta_window_actor_show (window_actor, effect);
  805. }
  806. void
  807. meta_compositor_hide_window (MetaCompositor *compositor,
  808. MetaWindow *window,
  809. MetaCompEffect effect)
  810. {
  811. MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  812. DEBUG_TRACE ("meta_compositor_hide_window\n");
  813. if (!window_actor)
  814. return;
  815. meta_window_actor_hide (window_actor, effect);
  816. }
  817. void
  818. meta_compositor_maximize_window (MetaCompositor *compositor,
  819. MetaWindow *window,
  820. MetaRectangle *old_rect,
  821. MetaRectangle *new_rect)
  822. {
  823. MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  824. DEBUG_TRACE ("meta_compositor_maximize_window\n");
  825. if (!window_actor)
  826. return;
  827. meta_window_actor_maximize (window_actor, old_rect, new_rect);
  828. }
  829. void
  830. meta_compositor_unmaximize_window (MetaCompositor *compositor,
  831. MetaWindow *window,
  832. MetaRectangle *old_rect,
  833. MetaRectangle *new_rect)
  834. {
  835. MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  836. DEBUG_TRACE ("meta_compositor_unmaximize_window\n");
  837. if (!window_actor)
  838. return;
  839. meta_window_actor_unmaximize (window_actor, old_rect, new_rect);
  840. }
  841. void
  842. meta_compositor_switch_workspace (MetaCompositor *compositor,
  843. MetaScreen *screen,
  844. MetaWorkspace *from,
  845. MetaWorkspace *to,
  846. MetaMotionDirection direction)
  847. {
  848. MetaCompScreen *info;
  849. gint to_indx, from_indx;
  850. info = meta_screen_get_compositor_data (screen);
  851. to_indx = meta_workspace_index (to);
  852. from_indx = meta_workspace_index (from);
  853. DEBUG_TRACE ("meta_compositor_switch_workspace\n");
  854. if (!info) /* During startup before manage_screen() */
  855. return;
  856. info->switch_workspace_in_progress++;
  857. if (!info->plugin_mgr ||
  858. !meta_plugin_manager_switch_workspace (info->plugin_mgr,
  859. from_indx,
  860. to_indx,
  861. direction))
  862. {
  863. info->switch_workspace_in_progress--;
  864. /* We have to explicitely call this to fix up stacking order of the
  865. * actors; this is because the abs stacking position of actors does not
  866. * necessarily change during the window hiding/unhiding, only their
  867. * relative position toward the destkop window.
  868. */
  869. meta_finish_workspace_switch (info);
  870. }
  871. }
  872. void
  873. meta_compositor_tile_window (MetaCompositor *compositor,
  874. MetaWindow *window,
  875. MetaRectangle *old_rect,
  876. MetaRectangle *new_rect)
  877. {
  878. MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  879. DEBUG_TRACE ("meta_compositor_tile_window\n");
  880. if (!window_actor)
  881. return;
  882. meta_window_actor_tile (window_actor, old_rect, new_rect);
  883. }
  884. static void
  885. sync_actor_stacking (MetaCompScreen *info)
  886. {
  887. GList *children;
  888. GList *tmp;
  889. GList *old;
  890. gboolean reordered;
  891. /* NB: The first entries in the lists are stacked the lowest */
  892. /* Restacking will trigger full screen redraws, so it's worth a
  893. * little effort to make sure we actually need to restack before
  894. * we go ahead and do it */
  895. children = clutter_container_get_children (CLUTTER_CONTAINER (info->window_group));
  896. reordered = FALSE;
  897. old = children;
  898. /* We allow for actors in the window group other than the actors we
  899. * know about, but it's up to a plugin to try and keep them stacked correctly
  900. * (we really need extra API to make that reliable.)
  901. */
  902. /* Of the actors we know, the bottom actor should be the background actor */
  903. while (old && old->data != info->background_actor && !META_IS_WINDOW_ACTOR (old->data))
  904. old = old->next;
  905. if (old == NULL || old->data != info->background_actor)
  906. {
  907. reordered = TRUE;
  908. goto done_with_check;
  909. }
  910. /* Then the window actors should follow in sequence */
  911. old = old->next;
  912. for (tmp = info->windows; tmp != NULL; tmp = tmp->next)
  913. {
  914. while (old && !META_IS_WINDOW_ACTOR (old->data))
  915. old = old->next;
  916. /* old == NULL: someone reparented a window out of the window group,
  917. * order undefined, always restack */
  918. if (old == NULL || old->data != tmp->data)
  919. {
  920. reordered = TRUE;
  921. goto done_with_check;
  922. }
  923. old = old->next;
  924. }
  925. done_with_check:
  926. g_list_free (children);
  927. if (!reordered)
  928. return;
  929. for (tmp = g_list_last (info->windows); tmp != NULL; tmp = tmp->prev)
  930. {
  931. MetaWindowActor *window_actor = tmp->data;
  932. clutter_actor_lower_bottom (CLUTTER_ACTOR (window_actor));
  933. }
  934. clutter_actor_lower_bottom (info->background_actor);
  935. }
  936. void
  937. meta_compositor_sync_stack (MetaCompositor *compositor,
  938. MetaScreen *screen,
  939. GList *stack)
  940. {
  941. GList *old_stack;
  942. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  943. DEBUG_TRACE ("meta_compositor_sync_stack\n");
  944. /* This is painful because hidden windows that we are in the process
  945. * of animating out of existence. They'll be at the bottom of the
  946. * stack of X windows, but we want to leave them in their old position
  947. * until the animation effect finishes.
  948. */
  949. /* Sources: first window is the highest */
  950. stack = g_list_copy (stack); /* The new stack of MetaWindow */
  951. old_stack = g_list_reverse (info->windows); /* The old stack of MetaWindowActor */
  952. info->windows = NULL;
  953. while (TRUE)
  954. {
  955. MetaWindowActor *old_actor = NULL, *stack_actor = NULL, *actor;
  956. MetaWindow *old_window = NULL, *stack_window = NULL, *window;
  957. /* Find the remaining top actor in our existing stack (ignoring
  958. * windows that have been hidden and are no longer animating) */
  959. while (old_stack)
  960. {
  961. old_actor = old_stack->data;
  962. old_window = meta_window_actor_get_meta_window (old_actor);
  963. if ((old_window->hidden || old_window->unmanaging) &&
  964. !meta_window_actor_effect_in_progress (old_actor))
  965. {
  966. old_stack = g_list_delete_link (old_stack, old_stack);
  967. old_actor = NULL;
  968. }
  969. else
  970. break;
  971. }
  972. /* And the remaining top actor in the new stack */
  973. while (stack)
  974. {
  975. stack_window = stack->data;
  976. stack_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (stack_window));
  977. if (!stack_actor)
  978. {
  979. meta_verbose ("Failed to find corresponding MetaWindowActor "
  980. "for window %s\n", meta_window_get_description (stack_window));
  981. stack = g_list_delete_link (stack, stack);
  982. }
  983. else
  984. break;
  985. }
  986. if (!old_actor && !stack_actor) /* Nothing more to stack */
  987. break;
  988. /* We usually prefer the window in the new stack, but if if we
  989. * found a hidden window in the process of being animated out
  990. * of existence in the old stack we use that instead. We've
  991. * filtered out non-animating hidden windows above.
  992. */
  993. if (old_actor &&
  994. (!stack_actor || old_window->hidden || old_window->unmanaging))
  995. {
  996. actor = old_actor;
  997. window = old_window;
  998. }
  999. else
  1000. {
  1001. actor = stack_actor;
  1002. window = stack_window;
  1003. }
  1004. /* OK, we know what actor we want next. Add it to our window
  1005. * list, and remove it from both source lists. (It will
  1006. * be at the front of at least one, hopefully it will be
  1007. * near the front of the other.)
  1008. */
  1009. info->windows = g_list_prepend (info->windows, actor);
  1010. stack = g_list_remove (stack, window);
  1011. old_stack = g_list_remove (old_stack, actor);
  1012. }
  1013. sync_actor_stacking (info);
  1014. }
  1015. void
  1016. meta_compositor_sync_window_geometry (MetaCompositor *compositor,
  1017. MetaWindow *window,
  1018. gboolean did_placement)
  1019. {
  1020. MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
  1021. MetaScreen *screen = meta_window_get_screen (window);
  1022. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1023. DEBUG_TRACE ("meta_compositor_sync_window_geometry\n");
  1024. g_return_if_fail (info);
  1025. if (!window_actor)
  1026. return;
  1027. meta_window_actor_sync_actor_geometry (window_actor, did_placement);
  1028. }
  1029. void
  1030. meta_compositor_sync_screen_size (MetaCompositor *compositor,
  1031. MetaScreen *screen,
  1032. guint width,
  1033. guint height)
  1034. {
  1035. MetaDisplay *display = meta_screen_get_display (screen);
  1036. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1037. Display *xdisplay;
  1038. Window xwin;
  1039. DEBUG_TRACE ("meta_compositor_sync_screen_size\n");
  1040. g_return_if_fail (info);
  1041. xdisplay = meta_display_get_xdisplay (display);
  1042. xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
  1043. XResizeWindow (xdisplay, xwin, width, height);
  1044. meta_background_actor_screen_size_changed (screen);
  1045. meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
  1046. meta_screen_get_screen_number (screen),
  1047. width, height);
  1048. }
  1049. static void
  1050. frame_callback (CoglOnscreen *onscreen,
  1051. CoglFrameEvent event,
  1052. CoglFrameInfo *frame_info,
  1053. void *user_data)
  1054. {
  1055. MetaCompScreen *info = user_data;
  1056. GList *l;
  1057. if (event == COGL_FRAME_EVENT_COMPLETE)
  1058. {
  1059. gint64 presentation_time_cogl = cogl_frame_info_get_presentation_time (frame_info);
  1060. gint64 presentation_time;
  1061. if (presentation_time_cogl != 0)
  1062. {
  1063. /* Cogl reports presentation in terms of its own clock, which is
  1064. * guaranteed to be in nanoseconds but with no specified base. The
  1065. * normal case with the open source GPU drivers on Linux 3.8 and
  1066. * newer is that the base of cogl_get_clock_time() is that of
  1067. * clock_gettime(CLOCK_MONOTONIC), so the same as g_get_monotonic_time),
  1068. * but there's no exposure of that through the API. clock_gettime()
  1069. * is fairly fast, so calling it twice and subtracting to get a
  1070. * nearly-zero number is acceptable, if a litle ugly.
  1071. */
  1072. CoglContext *context = cogl_framebuffer_get_context (COGL_FRAMEBUFFER (onscreen));
  1073. gint64 current_cogl_time = cogl_get_clock_time (context);
  1074. gint64 current_monotonic_time = g_get_monotonic_time ();
  1075. presentation_time =
  1076. current_monotonic_time + (presentation_time_cogl - current_cogl_time) / 1000;
  1077. }
  1078. else
  1079. {
  1080. presentation_time = 0;
  1081. }
  1082. for (l = info->windows; l; l = l->next)
  1083. meta_window_actor_frame_complete (l->data, frame_info, presentation_time);
  1084. }
  1085. }
  1086. static gboolean
  1087. meta_pre_paint_func (gpointer data)
  1088. {
  1089. GList *l;
  1090. MetaCompositor *compositor = data;
  1091. GSList *screens = meta_display_get_screens (compositor->display);
  1092. MetaCompScreen *info = meta_screen_get_compositor_data (screens->data);
  1093. MetaWindowActor *top_window;
  1094. MetaWindowActor *expected_unredirected_window = NULL;
  1095. if (info->onscreen == NULL)
  1096. {
  1097. info->onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer ());
  1098. info->frame_closure = cogl_onscreen_add_frame_callback (info->onscreen,
  1099. frame_callback,
  1100. info,
  1101. NULL);
  1102. }
  1103. if (info->windows == NULL)
  1104. return TRUE;;
  1105. top_window = g_list_last (info->windows)->data;
  1106. if (meta_window_actor_should_unredirect (top_window) &&
  1107. info->disable_unredirect_count == 0)
  1108. expected_unredirected_window = top_window;
  1109. if (info->unredirected_window != expected_unredirected_window)
  1110. {
  1111. if (info->unredirected_window != NULL)
  1112. {
  1113. meta_window_actor_set_redirected (info->unredirected_window, TRUE);
  1114. meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
  1115. NULL);
  1116. }
  1117. if (expected_unredirected_window != NULL)
  1118. {
  1119. meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (top_window)),
  1120. meta_window_actor_get_meta_window (top_window));
  1121. meta_window_actor_set_redirected (top_window, FALSE);
  1122. }
  1123. info->unredirected_window = expected_unredirected_window;
  1124. }
  1125. for (l = info->windows; l; l = l->next)
  1126. meta_window_actor_pre_paint (l->data);
  1127. if (compositor->frame_has_updated_xsurfaces)
  1128. {
  1129. /* We need to make sure that any X drawing that happens before
  1130. * the XDamageSubtract() for each window above is visible to
  1131. * subsequent GL rendering; the standardized way to do this is
  1132. * GL_EXT_X11_sync_object. Since this isn't implemented yet in
  1133. * mesa, we also have a path that relies on the implementation
  1134. * of the open source drivers.
  1135. *
  1136. * Anything else, we just hope for the best.
  1137. *
  1138. * Xorg and open source driver specifics:
  1139. *
  1140. * The X server makes sure to flush drawing to the kernel before
  1141. * sending out damage events, but since we use
  1142. * DamageReportBoundingBox there may be drawing between the last
  1143. * damage event and the XDamageSubtract() that needs to be
  1144. * flushed as well.
  1145. *
  1146. * Xorg always makes sure that drawing is flushed to the kernel
  1147. * before writing events or responses to the client, so any
  1148. * round trip request at this point is sufficient to flush the
  1149. * GLX buffers.
  1150. */
  1151. if (compositor->have_x11_sync_object)
  1152. compositor->have_x11_sync_object = meta_sync_ring_insert_wait ();
  1153. else
  1154. XSync (compositor->display->xdisplay, False);
  1155. }
  1156. return TRUE;
  1157. }
  1158. static gboolean
  1159. meta_post_paint_func (gpointer data)
  1160. {
  1161. MetaCompositor *compositor = data;
  1162. if (compositor->frame_has_updated_xsurfaces)
  1163. {
  1164. if (compositor->have_x11_sync_object)
  1165. compositor->have_x11_sync_object = meta_sync_ring_after_frame ();
  1166. compositor->frame_has_updated_xsurfaces = FALSE;
  1167. }
  1168. return TRUE;
  1169. }
  1170. static void
  1171. on_shadow_factory_changed (MetaShadowFactory *factory,
  1172. MetaCompositor *compositor)
  1173. {
  1174. GSList *screens = meta_display_get_screens (compositor->display);
  1175. GList *l;
  1176. GSList *sl;
  1177. for (sl = screens; sl; sl = sl->next)
  1178. {
  1179. MetaScreen *screen = sl->data;
  1180. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1181. if (!info)
  1182. continue;
  1183. for (l = info->windows; l; l = l->next)
  1184. meta_window_actor_invalidate_shadow (l->data);
  1185. }
  1186. }
  1187. /**
  1188. * meta_compositor_new: (skip)
  1189. *
  1190. */
  1191. MetaCompositor *
  1192. meta_compositor_new (MetaDisplay *display)
  1193. {
  1194. char *atom_names[] = {
  1195. "_XROOTPMAP_ID",
  1196. "_XSETROOT_ID",
  1197. "_NET_WM_WINDOW_OPACITY",
  1198. };
  1199. Atom atoms[G_N_ELEMENTS(atom_names)];
  1200. MetaCompositor *compositor;
  1201. Display *xdisplay = meta_display_get_xdisplay (display);
  1202. if (!composite_at_least_version (display, 0, 3))
  1203. return NULL;
  1204. compositor = g_new0 (MetaCompositor, 1);
  1205. compositor->display = display;
  1206. if (g_getenv("META_DISABLE_MIPMAPS"))
  1207. compositor->no_mipmaps = TRUE;
  1208. meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
  1209. XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
  1210. False, atoms);
  1211. g_signal_connect (meta_shadow_factory_get_default (),
  1212. "changed",
  1213. G_CALLBACK (on_shadow_factory_changed),
  1214. compositor);
  1215. compositor->atom_x_root_pixmap = atoms[0];
  1216. compositor->atom_x_set_root = atoms[1];
  1217. compositor->atom_net_wm_window_opacity = atoms[2];
  1218. compositor->pre_paint_func_id =
  1219. clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_PRE_PAINT,
  1220. meta_pre_paint_func,
  1221. compositor,
  1222. NULL);
  1223. compositor->post_paint_func_id =
  1224. clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
  1225. meta_post_paint_func,
  1226. compositor,
  1227. NULL);
  1228. return compositor;
  1229. }
  1230. /**
  1231. * meta_get_overlay_window: (skip)
  1232. *
  1233. */
  1234. Window
  1235. meta_get_overlay_window (MetaScreen *screen)
  1236. {
  1237. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1238. return info->output;
  1239. }
  1240. /**
  1241. * meta_disable_unredirect_for_screen:
  1242. * @screen: a #MetaScreen
  1243. *
  1244. * Disables unredirection, can be usefull in situations where having
  1245. * unredirected windows is undesireable like when recording a video.
  1246. *
  1247. */
  1248. void
  1249. meta_disable_unredirect_for_screen (MetaScreen *screen)
  1250. {
  1251. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1252. if (info != NULL)
  1253. info->disable_unredirect_count = info->disable_unredirect_count + 1;
  1254. }
  1255. /**
  1256. * meta_enable_unredirect_for_screen:
  1257. * @screen: a #MetaScreen
  1258. *
  1259. * Enables unredirection which reduces the overhead for apps like games.
  1260. *
  1261. */
  1262. void
  1263. meta_enable_unredirect_for_screen (MetaScreen *screen)
  1264. {
  1265. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1266. if (info != NULL && info->disable_unredirect_count == 0)
  1267. g_warning ("Called enable_unredirect_for_screen while unredirection is enabled.");
  1268. if (info != NULL && info->disable_unredirect_count > 0)
  1269. info->disable_unredirect_count = info->disable_unredirect_count - 1;
  1270. }
  1271. #define FLASH_TIME_MS 50
  1272. static void
  1273. flash_out_completed (ClutterAnimation *animation,
  1274. ClutterActor *flash)
  1275. {
  1276. clutter_actor_destroy (flash);
  1277. }
  1278. static void
  1279. flash_in_completed (ClutterAnimation *animation,
  1280. ClutterActor *flash)
  1281. {
  1282. clutter_actor_animate (flash, CLUTTER_EASE_IN_QUAD,
  1283. FLASH_TIME_MS,
  1284. "opacity", 0,
  1285. "signal-after::completed", flash_out_completed, flash,
  1286. NULL);
  1287. }
  1288. void
  1289. meta_compositor_flash_screen (MetaCompositor *compositor,
  1290. MetaScreen *screen)
  1291. {
  1292. ClutterActor *stage;
  1293. ClutterActor *flash;
  1294. ClutterColor black = { 0, 0, 0, 255 };
  1295. gfloat width, height;
  1296. stage = meta_get_stage_for_screen (screen);
  1297. clutter_actor_get_size (stage, &width, &height);
  1298. flash = clutter_rectangle_new_with_color (&black);
  1299. clutter_actor_set_size (flash, width, height);
  1300. clutter_actor_set_opacity (flash, 0);
  1301. clutter_container_add_actor (CLUTTER_CONTAINER (stage), flash);
  1302. clutter_actor_animate (flash, CLUTTER_EASE_OUT_QUAD,
  1303. FLASH_TIME_MS,
  1304. "opacity", 192,
  1305. "signal-after::completed", flash_in_completed, flash,
  1306. NULL);
  1307. }
  1308. void
  1309. meta_compositor_show_tile_preview (MetaCompositor *compositor,
  1310. MetaScreen *screen,
  1311. MetaWindow *window,
  1312. MetaRectangle *tile_rect,
  1313. int tile_monitor_number,
  1314. guint snap_queued)
  1315. {
  1316. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1317. if (!info->plugin_mgr)
  1318. return;
  1319. meta_plugin_manager_show_tile_preview (info->plugin_mgr,
  1320. window, tile_rect, tile_monitor_number,
  1321. snap_queued);
  1322. }
  1323. void
  1324. meta_compositor_hide_tile_preview (MetaCompositor *compositor,
  1325. MetaScreen *screen)
  1326. {
  1327. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1328. if (!info->plugin_mgr)
  1329. return;
  1330. meta_plugin_manager_hide_tile_preview (info->plugin_mgr);
  1331. }
  1332. void
  1333. meta_compositor_show_hud_preview (MetaCompositor *compositor,
  1334. MetaScreen *screen,
  1335. guint current_proximity_zone,
  1336. MetaRectangle *work_area,
  1337. guint snap_queued)
  1338. {
  1339. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1340. if (!info->plugin_mgr)
  1341. return;
  1342. meta_plugin_manager_show_hud_preview (info->plugin_mgr,
  1343. current_proximity_zone,
  1344. work_area,
  1345. snap_queued);
  1346. }
  1347. void
  1348. meta_compositor_hide_hud_preview (MetaCompositor *compositor,
  1349. MetaScreen *screen)
  1350. {
  1351. MetaCompScreen *info = meta_screen_get_compositor_data (screen);
  1352. if (!info->plugin_mgr)
  1353. return;
  1354. meta_plugin_manager_hide_hud_preview (info->plugin_mgr);
  1355. }
  1356. /**
  1357. * meta_compositor_monotonic_time_to_server_time:
  1358. * @display: a #MetaDisplay
  1359. * @monotonic_time: time in the units of g_get_monotonic_time()
  1360. *
  1361. * _NET_WM_FRAME_DRAWN and _NET_WM_FRAME_TIMINGS messages represent time
  1362. * as a "high resolution server time" - this is the server time interpolated
  1363. * to microsecond resolution. The advantage of this time representation
  1364. * is that if X server is running on the same computer as a client, and
  1365. * the Xserver uses 'clock_gettime(CLOCK_MONOTONIC, ...)' for the server
  1366. * time, the client can detect this, and all such clients will share a
  1367. * a time representation with high accuracy. If there is not a common
  1368. * time source, then the time synchronization will be less accurate.
  1369. */
  1370. gint64
  1371. meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
  1372. gint64 monotonic_time)
  1373. {
  1374. MetaCompositor *compositor = display->compositor;
  1375. if (compositor->server_time_query_time == 0 ||
  1376. (!compositor->server_time_is_monotonic_time &&
  1377. monotonic_time > compositor->server_time_query_time + 10*1000*1000)) /* 10 seconds */
  1378. {
  1379. guint32 server_time = meta_display_get_current_time_roundtrip (display);
  1380. gint64 server_time_usec = (gint64)server_time * 1000;
  1381. gint64 current_monotonic_time = g_get_monotonic_time ();
  1382. compositor->server_time_query_time = current_monotonic_time;
  1383. /* If the server time is within a second of the monotonic time,
  1384. * we assume that they are identical. This seems like a big margin,
  1385. * but we want to be as robust as possible even if the system
  1386. * is under load and our processing of the server response is
  1387. * delayed.
  1388. */
  1389. if (server_time_usec > current_monotonic_time - 1000*1000 &&
  1390. server_time_usec < current_monotonic_time + 1000*1000)
  1391. compositor->server_time_is_monotonic_time = TRUE;
  1392. compositor->server_time_offset = server_time_usec - current_monotonic_time;
  1393. }
  1394. if (compositor->server_time_is_monotonic_time)
  1395. return monotonic_time;
  1396. else
  1397. return monotonic_time + compositor->server_time_offset;
  1398. }