static MetaWindow * test_client_find_window (TestClient *client, const char *window_id, GError **error) { MetaDisplay *display = meta_get_display (); GSList *windows = meta_display_list_windows (display, META_LIST_INCLUDE_OVERRIDE_REDIRECT); MetaWindow *result = NULL; char *expected_title = g_strdup_printf ("test/%s/%s", client->id, window_id); GSList *l; for (l = windows; l; l = l->next) { MetaWindow *window = l->data; if (g_strcmp0 (window->title, expected_title) == 0) { result = window; break; } } g_slist_free (windows); g_free (expected_title); if (result == NULL) g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_RUNTIME_ERROR, "window %s/%s isn't known to Mutter", client->id, window_id); return result; }
static void sync_focus_surface (MetaWaylandPointer *pointer) { MetaDisplay *display = meta_get_display (); switch (display->event_route) { case META_EVENT_ROUTE_WINDOW_OP: case META_EVENT_ROUTE_COMPOSITOR_GRAB: case META_EVENT_ROUTE_FRAME_BUTTON: /* The compositor has a grab, so remove our focus... */ meta_wayland_pointer_set_focus (pointer, NULL); break; case META_EVENT_ROUTE_NORMAL: case META_EVENT_ROUTE_WAYLAND_POPUP: { const MetaWaylandPointerGrabInterface *interface = pointer->grab->interface; interface->focus (pointer->grab, pointer->current); } break; default: g_assert_not_reached (); } }
void meta_session_shutdown (void) { /* Change our restart mode to IfRunning */ SmProp prop1; SmPropValue prop1val; SmProp *props[1]; char hint = SmRestartIfRunning; if (!meta_get_display ()) { meta_verbose ("Cannot close session because there is no display"); return; } warn_about_lame_clients_and_finish_interact (FALSE); if (session_connection == NULL) return; prop1.name = SmRestartStyleHint; prop1.type = SmCARD8; prop1.num_vals = 1; prop1.vals = &prop1val; prop1val.value = &hint; prop1val.length = 1; props[0] = &prop1; SmcSetProperties (session_connection, 1, props); }
static void create_wl_shell_surface_window (MetaWaylandSurface *surface) { MetaWaylandWlShellSurface *wl_shell_surface = META_WAYLAND_WL_SHELL_SURFACE (surface->role); MetaWaylandSurface *parent; GList *l; surface->window = meta_window_wayland_new (meta_get_display (), surface); meta_wayland_surface_set_window (surface, surface->window); if (wl_shell_surface->title) meta_window_set_title (surface->window, wl_shell_surface->title); if (wl_shell_surface->wm_class) meta_window_set_wm_class (surface->window, wl_shell_surface->wm_class, wl_shell_surface->wm_class); parent = wl_shell_surface->parent_surface; if (parent && parent->window) sync_wl_shell_parent_relationship (surface, parent); for (l = wl_shell_surface->children; l; l = l->next) { MetaWaylandSurface *child = l->data; if (child->window) sync_wl_shell_parent_relationship (child, surface); } }
static gboolean is_input_event (XEvent *event) { MetaDisplay *display = meta_get_display (); return (event->type == GenericEvent && event->xcookie.extension == display->xinput_opcode); }
static void async_waiter_destroy (AsyncWaiter *waiter) { Display *xdisplay = meta_get_display ()->xdisplay; XSyncDestroyAlarm (xdisplay, waiter->alarm); XSyncDestroyCounter (xdisplay, waiter->counter); g_main_loop_unref (waiter->loop); }
static void meta_finalize (void) { MetaDisplay *display = meta_get_display (); if (display) meta_display_close (display, CurrentTime); /* I doubt correct timestamps matter here */ }
static void wl_shell_surface_pong (struct wl_client *client, struct wl_resource *resource, uint32_t serial) { MetaDisplay *display = meta_get_display (); meta_display_pong_for_serial (display, serial); }
static void handle_host_xevent (MetaBackend *backend, XEvent *event) { MetaBackendX11 *x11 = META_BACKEND_X11 (backend); MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); gboolean bypass_clutter = FALSE; XGetEventData (priv->xdisplay, &event->xcookie); { MetaDisplay *display = meta_get_display (); if (display) { MetaCompositor *compositor = display->compositor; if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event)) bypass_clutter = TRUE; } } if (event->type == (priv->xsync_event_base + XSyncAlarmNotify)) handle_alarm_notify (backend, event); if (event->type == priv->xkb_event_base) { XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event; if (xkb_ev->device == META_VIRTUAL_CORE_KEYBOARD_ID) { switch (xkb_ev->xkb_type) { case XkbNewKeyboardNotify: case XkbMapNotify: keymap_changed (backend); default: break; } } } { MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend); if (META_IS_MONITOR_MANAGER_XRANDR (manager) && meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event)) bypass_clutter = TRUE; } if (!bypass_clutter) { handle_input_event (x11, event); clutter_x11_handle_event (event); } XFreeEventData (priv->xdisplay, &event->xcookie); }
static void async_waiter_set_and_wait (AsyncWaiter *waiter) { Display *xdisplay = meta_get_display ()->xdisplay; int wait_value = async_waiter_next_value (waiter); XSyncValue sync_value; XSyncIntToValue (&sync_value, wait_value); XSyncSetCounter (xdisplay, waiter->counter, sync_value); async_waiter_wait (waiter, wait_value); }
static void meta_finalize (void) { MetaDisplay *display = meta_get_display (); if (display) meta_display_close (display, CurrentTime); /* I doubt correct timestamps matter here */ if (meta_is_wayland_compositor ()) meta_wayland_finalize (); }
static gboolean test_case_check_xserver_stacking (TestCase *test, GError **error) { MetaDisplay *display = meta_get_display (); GString *local_string = g_string_new (NULL); GString *x11_string = g_string_new (NULL); int i; guint64 *windows; int n_windows; meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows); for (i = 0; i < n_windows; i++) { if (META_STACK_ID_IS_X11 (windows[i])) { if (local_string->len > 0) g_string_append_c (local_string, ' '); g_string_append_printf (local_string, "%#lx", (Window)windows[i]); } } Window root; Window parent; Window *children; unsigned int n_children; XQueryTree (display->xdisplay, meta_screen_get_xroot (display->screen), &root, &parent, &children, &n_children); for (i = 0; i < (int)n_children; i++) { if (x11_string->len > 0) g_string_append_c (x11_string, ' '); g_string_append_printf (x11_string, "%#lx", (Window)children[i]); } if (strcmp (x11_string->str, local_string->str) != 0) g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED, "xserver stacking: x11='%s', local='%s'", x11_string->str, local_string->str); XFree (children); g_string_free (local_string, TRUE); g_string_free (x11_string, TRUE); return *error == NULL; }
gboolean alex_windows_loop (gpointer data) { MetaDisplay *alexdisplay; GSList *display_windows; alexdisplay = meta_get_display (); display_windows = meta_display_list_windows (alexdisplay); g_slist_foreach (display_windows, alex_window_proc, NULL); return (1); }
static MetaCursorSprite * get_displayed_cursor (MetaCursorTracker *tracker) { MetaDisplay *display = meta_get_display (); if (!tracker->is_showing) return NULL; if (meta_display_windows_are_interactable (display)) { if (tracker->has_window_cursor) return tracker->window_cursor; } return tracker->root_cursor; }
static gboolean test_case_destroy (TestCase *test, GError **error) { /* Failures when cleaning up the test case aren't recoverable, since we'll * pollute the subsequent test cases, so we just return the error, and * skip the rest of the cleanup. */ GHashTableIter iter; gpointer key, value; g_hash_table_iter_init (&iter, test->clients); while (g_hash_table_iter_next (&iter, &key, &value)) { if (!test_client_do (value, error, "destroy_all", NULL)) return FALSE; } if (!test_case_wait (test, error)) return FALSE; if (!test_case_assert_stacking (test, NULL, 0, error)) return FALSE; if (!test_case_check_warnings (test, error)) return FALSE; g_hash_table_iter_init (&iter, test->clients); while (g_hash_table_iter_next (&iter, &key, &value)) test_client_destroy (value); async_waiter_destroy (test->waiter); meta_display_set_alarm_filter (meta_get_display (), NULL, NULL); g_hash_table_destroy (test->clients); g_free (test); g_log_remove_handler ("mutter", test->log_handler_id); return TRUE; }
static TestCase * test_case_new (void) { TestCase *test = g_new0 (TestCase, 1); test->log_handler_id = g_log_set_handler ("mutter", G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING, test_case_log_func, test); meta_display_set_alarm_filter (meta_get_display (), test_case_alarm_filter, test); test->clients = g_hash_table_new (g_str_hash, g_str_equal); test->waiter = async_waiter_new (); test->loop = g_main_loop_new (NULL, FALSE); return test; }
static void xdg_shell_get_xdg_surface (struct wl_client *client, struct wl_resource *resource, guint32 id, struct wl_resource *surface_resource) { MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandXdgSurface *xdg_surface; MetaWindow *window; if (META_IS_WAYLAND_XDG_SURFACE (surface->role) && META_WAYLAND_XDG_SURFACE (surface->role)->resource) { wl_resource_post_error (surface_resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "xdg_shell::get_xdg_surface already requested"); return; } if (!meta_wayland_surface_assign_role (surface, META_TYPE_WAYLAND_XDG_SURFACE)) { wl_resource_post_error (resource, XDG_SHELL_ERROR_ROLE, "wl_surface@%d already has a different role", wl_resource_get_id (surface->resource)); return; } xdg_surface = META_WAYLAND_XDG_SURFACE (surface->role); xdg_surface->resource = wl_resource_create (client, &xdg_surface_interface, wl_resource_get_version (resource), id); wl_resource_set_implementation (xdg_surface->resource, &meta_wayland_xdg_surface_interface, xdg_surface, xdg_surface_destructor); xdg_surface->xdg_shell_resource = resource; window = meta_window_wayland_new (meta_get_display (), surface); meta_wayland_surface_set_window (surface, window); }
static AsyncWaiter * async_waiter_new (void) { AsyncWaiter *waiter = g_new0 (AsyncWaiter, 1); Display *xdisplay = meta_get_display ()->xdisplay; XSyncValue value; XSyncAlarmAttributes attr; waiter->counter_value = 0; XSyncIntToValue (&value, waiter->counter_value); waiter->counter = XSyncCreateCounter (xdisplay, value); attr.trigger.counter = waiter->counter; attr.trigger.test_type = XSyncPositiveComparison; /* Initialize to one greater than the current value */ attr.trigger.value_type = XSyncRelative; XSyncIntToValue (&attr.trigger.wait_value, 1); /* After triggering, increment test_value by this until * until the test condition is false */ XSyncIntToValue (&attr.delta, 1); /* we want events (on by default anyway) */ attr.events = True; waiter->alarm = XSyncCreateAlarm (xdisplay, XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType | XSyncCADelta | XSyncCAEvents, &attr); waiter->loop = g_main_loop_new (NULL, FALSE); return waiter; }
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, XEvent *xevent) { MetaDisplay *display = meta_get_display (); XFixesCursorNotifyEvent *notify_event; if (meta_is_wayland_compositor ()) return FALSE; if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify) return FALSE; notify_event = (XFixesCursorNotifyEvent *)xevent; if (notify_event->subtype != XFixesDisplayCursorNotify) return FALSE; g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref); return TRUE; }
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, XEvent *xevent) { MetaDisplay *display = meta_get_display (); XFixesCursorNotifyEvent *notify_event; if (meta_is_wayland_compositor ()) return FALSE; if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify) return FALSE; notify_event = (XFixesCursorNotifyEvent *)xevent; if (notify_event->subtype != XFixesDisplayCursorNotify) return FALSE; g_clear_object (&tracker->xfixes_cursor); g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); return TRUE; }
void meta_invalidate_default_icons (void) { MetaDisplay *display = meta_get_display (); GSList *windows; GSList *l; if (display == NULL) return; /* We can validly be called before the display is opened. */ windows = meta_display_list_windows (display); for (l = windows; l != NULL; l = l->next) { MetaWindow *window = (MetaWindow*)l->data; if (window->icon_cache.origin == USING_FALLBACK_ICON) { meta_icon_cache_free (&(window->icon_cache)); meta_window_update_icon_now (window); } } g_slist_free (windows); }
static void ensure_xfixes_cursor (MetaCursorTracker *tracker) { MetaDisplay *display = meta_get_display (); XFixesCursorImage *cursor_image; CoglTexture2D *sprite; guint8 *cursor_data; gboolean free_cursor_data; CoglContext *ctx; CoglError *error = NULL; if (tracker->xfixes_cursor) return; cursor_image = XFixesGetCursorImage (display->xdisplay); if (!cursor_image) return; /* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit * quantities as arrays of long; we need to convert on 64 bit */ if (sizeof(long) == 4) { cursor_data = (guint8 *)cursor_image->pixels; free_cursor_data = FALSE; } else { int i, j; guint32 *cursor_words; gulong *p; guint32 *q; cursor_words = g_new (guint32, cursor_image->width * cursor_image->height); cursor_data = (guint8 *)cursor_words; p = cursor_image->pixels; q = cursor_words; for (j = 0; j < cursor_image->height; j++) for (i = 0; i < cursor_image->width; i++) *(q++) = *(p++); free_cursor_data = TRUE; } ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); sprite = cogl_texture_2d_new_from_data (ctx, cursor_image->width, cursor_image->height, CLUTTER_CAIRO_FORMAT_ARGB32, cursor_image->width * 4, /* stride */ cursor_data, &error); if (free_cursor_data) g_free (cursor_data); if (error != NULL) { meta_warning ("Failed to allocate cursor sprite texture: %s\n", error->message); cogl_error_free (error); } if (sprite != NULL) { MetaCursorSprite *cursor_sprite = meta_cursor_sprite_new (); meta_cursor_sprite_set_texture (cursor_sprite, sprite, cursor_image->xhot, cursor_image->yhot); cogl_object_unref (sprite); tracker->xfixes_cursor = cursor_sprite; } XFree (cursor_image); }
static void handle_host_xevent (MetaBackend *backend, XEvent *event) { MetaBackendX11 *x11 = META_BACKEND_X11 (backend); MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); gboolean bypass_clutter = FALSE; XGetEventData (priv->xdisplay, &event->xcookie); { MetaDisplay *display = meta_get_display (); if (display) { MetaCompositor *compositor = display->compositor; if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event)) bypass_clutter = TRUE; } } if (priv->mode == META_BACKEND_X11_MODE_NESTED && event->type == FocusIn) { #ifdef HAVE_WAYLAND Window xwin = meta_backend_x11_get_xwindow(x11); XEvent xev; if (event->xfocus.window == xwin) { /* Since we've selected for KeymapStateMask, every FocusIn is followed immediately * by a KeymapNotify event */ XMaskEvent(priv->xdisplay, KeymapStateMask, &xev); MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); meta_wayland_compositor_update_key_state (compositor, xev.xkeymap.key_vector, 32, 8); } #else g_assert_not_reached (); #endif } if (event->type == (priv->xsync_event_base + XSyncAlarmNotify)) handle_alarm_notify (backend, event); if (event->type == priv->xkb_event_base) { XkbEvent *xkb_ev = (XkbEvent *) event; if (xkb_ev->any.device == META_VIRTUAL_CORE_KEYBOARD_ID) { switch (xkb_ev->any.xkb_type) { case XkbNewKeyboardNotify: case XkbMapNotify: keymap_changed (backend); break; case XkbStateNotify: if (xkb_ev->state.changed & XkbGroupLockMask) { if (priv->locked_group != xkb_ev->state.locked_group) XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, priv->locked_group); } break; default: break; } } } { MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend); if (META_IS_MONITOR_MANAGER_XRANDR (manager) && meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event)) bypass_clutter = TRUE; } if (!bypass_clutter) { handle_input_event (x11, event); clutter_x11_handle_event (event); } XFreeEventData (priv->xdisplay, &event->xcookie); }
static void xdg_shell_get_xdg_popup (struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource, struct wl_resource *seat_resource, uint32_t serial, int32_t x, int32_t y) { MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandPopupSurface *popup_surface; MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); MetaWaylandSurface *top_popup; MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); MetaWindow *window; MetaDisplay *display = meta_get_display (); MetaWaylandXdgPopup *xdg_popup; MetaWaylandPopup *popup; if (META_IS_WAYLAND_XDG_POPUP (surface->role) && META_WAYLAND_XDG_POPUP (surface->role)->resource) { wl_resource_post_error (surface_resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "xdg_shell::get_xdg_popup already requested"); return; } if (!meta_wayland_surface_assign_role (surface, META_TYPE_WAYLAND_XDG_POPUP)) { wl_resource_post_error (resource, XDG_SHELL_ERROR_ROLE, "wl_surface@%d already has a different role", wl_resource_get_id (surface->resource)); return; } if (parent_surf == NULL || parent_surf->window == NULL || (!META_IS_WAYLAND_XDG_POPUP (parent_surf->role) && !META_IS_WAYLAND_XDG_SURFACE (parent_surf->role))) { wl_resource_post_error (resource, XDG_SHELL_ERROR_INVALID_POPUP_PARENT, "invalid parent surface"); return; } top_popup = meta_wayland_pointer_get_top_popup (&seat->pointer); if ((top_popup == NULL && !META_IS_WAYLAND_XDG_SURFACE (parent_surf->role)) || (top_popup != NULL && parent_surf != top_popup)) { wl_resource_post_error (resource, XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP, "parent not top most surface"); return; } xdg_popup = META_WAYLAND_XDG_POPUP (surface->role); xdg_popup->resource = wl_resource_create (client, &xdg_popup_interface, wl_resource_get_version (resource), id); wl_resource_set_implementation (xdg_popup->resource, &meta_wayland_xdg_popup_interface, xdg_popup, xdg_popup_destructor); xdg_popup->xdg_shell_resource = resource; if (!meta_wayland_seat_can_popup (seat, serial)) { xdg_popup_send_popup_done (xdg_popup->resource); return; } xdg_popup->parent_surface = parent_surf; xdg_popup->parent_destroy_listener.notify = handle_popup_parent_destroyed; wl_resource_add_destroy_listener (parent_surf->resource, &xdg_popup->parent_destroy_listener); window = meta_window_wayland_new (display, surface); meta_window_wayland_place_relative_to (window, parent_surf->window, x, y); window->showing_for_first_time = FALSE; meta_wayland_surface_set_window (surface, window); meta_window_focus (window, meta_display_get_current_time (display)); popup_surface = META_WAYLAND_POPUP_SURFACE (surface->role); popup = meta_wayland_pointer_start_popup_grab (&seat->pointer, popup_surface); if (popup == NULL) { xdg_popup_send_popup_done (xdg_popup->resource); meta_wayland_surface_destroy_window (surface); return; } xdg_popup->popup = popup; }
static void warn_about_lame_clients_and_finish_interact (gboolean shutdown) { GSList *lame = NULL; GSList *windows; GSList *lame_details = NULL; GSList *tmp; GSList *columns = NULL; GPid pid; windows = meta_display_list_windows (meta_get_display ()); tmp = windows; while (tmp != NULL) { MetaWindow *window; window = tmp->data; /* only complain about normal windows, the others * are kind of dumb to worry about */ if (window->sm_client_id == NULL && window->type == META_WINDOW_NORMAL) lame = g_slist_prepend (lame, window); tmp = tmp->next; } g_slist_free (windows); if (lame == NULL) { /* No lame apps. */ finish_interact (shutdown); return; } columns = g_slist_prepend (columns, "Window"); columns = g_slist_prepend (columns, "Class"); lame = g_slist_sort (lame, (GCompareFunc) windows_cmp_by_title); tmp = lame; while (tmp != NULL) { MetaWindow *w = tmp->data; lame_details = g_slist_prepend (lame_details, w->res_class ? w->res_class : ""); lame_details = g_slist_prepend (lame_details, w->title); tmp = tmp->next; } g_slist_free (lame); pid = meta_show_dialog("--list", _("These windows do not support "save current setup" " "and will have to be restarted manually next time " "you log in."), "240", meta_screen_get_screen_number (meta_get_display()->active_screen), NULL, NULL, None, columns, lame_details); g_slist_free (lame_details); g_child_watch_add (pid, dialog_closed, GINT_TO_POINTER (shutdown)); }
static void save_state (void) { char *consortium_dir; char *session_dir; FILE *outfile; GSList *windows; GSList *tmp; int stack_position; g_assert (client_id); outfile = NULL; /* * g_get_user_config_dir() is guaranteed to return an existing directory. * Eventually, if SM stays with the WM, I'd like to make this * something like <config>/window_placement in a standard format. * Future optimisers should note also that by the time we get here * we probably already have full_save_path figured out and therefore * can just use the directory name from that. */ consortium_dir = g_strconcat (g_get_user_config_dir (), G_DIR_SEPARATOR_S "consortium", NULL); session_dir = g_strconcat (consortium_dir, G_DIR_SEPARATOR_S "sessions", NULL); if (mkdir (consortium_dir, 0700) < 0 && errno != EEXIST) { meta_warning (_("Could not create directory '%s': %s\n"), consortium_dir, g_strerror (errno)); } if (mkdir (session_dir, 0700) < 0 && errno != EEXIST) { meta_warning (_("Could not create directory '%s': %s\n"), session_dir, g_strerror (errno)); } meta_topic (META_DEBUG_SM, "Saving session to '%s'\n", full_save_file ()); outfile = fopen (full_save_file (), "w"); if (outfile == NULL) { meta_warning (_("Could not open session file '%s' for writing: %s\n"), full_save_file (), g_strerror (errno)); goto out; } /* The file format is: * <consortium_session id="foo"> * <window id="bar" class="XTerm" name="xterm" title="/foo/bar" role="blah" type="normal" stacking="5"> * <workspace index="2"/> * <workspace index="4"/> * <sticky/> <minimized/> <maximized/> * <geometry x="100" y="100" width="200" height="200" gravity="northwest"/> * </window> * </consortium_session> * * Note that attributes on <window> are the match info we use to * see if the saved state applies to a restored window, and * child elements are the saved state to be applied. * */ fprintf (outfile, "<consortium_session id=\"%s\">\n", client_id); windows = meta_display_list_windows (meta_get_display ()); stack_position = 0; windows = g_slist_sort (windows, meta_display_stack_cmp); tmp = windows; stack_position = 0; while (tmp != NULL) { MetaWindow *window; window = tmp->data; if (window->sm_client_id) { char *sm_client_id; char *res_class; char *res_name; char *role; char *title; /* client id, class, name, role are not expected to be * in UTF-8 (I think they are in XPCS which is Latin-1? * in practice they are always ascii though.) */ sm_client_id = encode_text_as_utf8_markup (window->sm_client_id); res_class = window->res_class ? encode_text_as_utf8_markup (window->res_class) : NULL; res_name = window->res_name ? encode_text_as_utf8_markup (window->res_name) : NULL; role = window->role ? encode_text_as_utf8_markup (window->role) : NULL; if (window->title) title = g_markup_escape_text (window->title, -1); else title = NULL; meta_topic (META_DEBUG_SM, "Saving session managed window %s, client ID '%s'\n", window->desc, window->sm_client_id); fprintf (outfile, " <window id=\"%s\" class=\"%s\" name=\"%s\" title=\"%s\" role=\"%s\" type=\"%s\" stacking=\"%d\">\n", sm_client_id, res_class ? res_class : "", res_name ? res_name : "", title ? title : "", role ? role : "", window_type_to_string (window->type), stack_position); g_free (sm_client_id); g_free (res_class); g_free (res_name); g_free (role); g_free (title); /* Sticky */ if (window->on_all_workspaces) fputs (" <sticky/>\n", outfile); /* Minimized */ if (window->minimized) fputs (" <minimized/>\n", outfile); /* Maximized */ if (META_WINDOW_MAXIMIZED (window)) { fprintf (outfile, " <maximized saved_x=\"%d\" saved_y=\"%d\" saved_width=\"%d\" saved_height=\"%d\"/>\n", window->saved_rect.x, window->saved_rect.y, window->saved_rect.width, window->saved_rect.height); } /* Workspaces we're on */ { int n; n = meta_workspace_index (window->workspace); fprintf (outfile, " <workspace index=\"%d\"/>\n", n); } /* Gravity */ { int x, y, w, h; meta_window_get_geometry (window, &x, &y, &w, &h); fprintf (outfile, " <geometry x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" gravity=\"%s\"/>\n", x, y, w, h, meta_gravity_to_string (window->size_hints.win_gravity)); } fputs (" </window>\n", outfile); } else { meta_topic (META_DEBUG_SM, "Not saving window '%s', not session managed\n", window->desc); } tmp = tmp->next; ++stack_position; } g_slist_free (windows); fputs ("</consortium_session>\n", outfile); out: if (outfile) { /* FIXME need a dialog for this */ if (ferror (outfile)) { meta_warning (_("Error writing session file '%s': %s\n"), full_save_file (), g_strerror (errno)); } if (fclose (outfile)) { meta_warning (_("Error closing session file '%s': %s\n"), full_save_file (), g_strerror (errno)); } } g_free (consortium_dir); g_free (session_dir); }
void meta_retheme_all (void) { if (meta_get_display ()) meta_display_retheme_all (); }
static gboolean test_case_assert_stacking (TestCase *test, char **expected_windows, int n_expected_windows, GError **error) { MetaDisplay *display = meta_get_display (); guint64 *windows; int n_windows; GString *stack_string = g_string_new (NULL); GString *expected_string = g_string_new (NULL); int i; meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows); for (i = 0; i < n_windows; i++) { MetaWindow *window = meta_display_lookup_stack_id (display, windows[i]); if (window != NULL && window->title) { /* See comment in meta_ui_new() about why the dummy window for GTK+ theming * is managed as a MetaWindow. */ if (META_STACK_ID_IS_X11 (windows[i]) && meta_ui_window_is_dummy (display->screen->ui, windows[i])) continue; if (stack_string->len > 0) g_string_append_c (stack_string, ' '); if (g_str_has_prefix (window->title, "test/")) g_string_append (stack_string, window->title + 5); else g_string_append_printf (stack_string, "(%s)", window->title); } else if (windows[i] == display->screen->guard_window) { if (stack_string->len > 0) g_string_append_c (stack_string, ' '); g_string_append_c (stack_string, '|'); } } for (i = 0; i < n_expected_windows; i++) { if (expected_string->len > 0) g_string_append_c (expected_string, ' '); g_string_append (expected_string, expected_windows[i]); } /* Don't require '| ' as a prefix if there are no hidden windows - we * remove the prefix from the actual string instead of adding it to the * expected string for clarity of the error message */ if (index (expected_string->str, '|') == NULL && stack_string->str[0] == '|') { g_string_erase (stack_string, 0, stack_string->str[1] == ' ' ? 2 : 1); } if (strcmp (expected_string->str, stack_string->str) != 0) { g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED, "stacking: expected='%s', actual='%s'", expected_string->str, stack_string->str); } g_string_free (stack_string, TRUE); g_string_free (expected_string, TRUE); return *error == NULL; }
static gboolean on_idle_end_grab(guint timestamp) { meta_verbose ("%s\n", __func__); meta_display_end_grab_op(meta_get_display(), timestamp); return G_SOURCE_REMOVE; }