/* Switch to requested view */ static void _xfdashboard_application_switch_to_view(XfdashboardApplication *self, const gchar *inInternalViewName) { GSList *stages, *iter; g_return_if_fail(XFDASHBOARD_IS_APPLICATION(self)); /* If no view name was specified then do nothing and return immediately */ if(!inInternalViewName || !inInternalViewName[0]) { g_debug("No view to switch to specified"); return; } /* Iterate through list of stages and set specified view at stage */ g_debug("Trying to switch to view '%s'", inInternalViewName); stages=clutter_stage_manager_list_stages(clutter_stage_manager_get_default()); for(iter=stages; iter; iter=g_slist_next(iter)) { /* Tell stage to switch view */ if(XFDASHBOARD_IS_STAGE(iter->data)) { xfdashboard_stage_set_switch_to_view(XFDASHBOARD_STAGE(iter->data), inInternalViewName); } } }
ClutterActor * _clutter_backend_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error) { ClutterBackendClass *klass; ClutterStageManager *stage_manager; ClutterActor *stage = NULL; g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), FALSE); g_return_val_if_fail (CLUTTER_IS_STAGE (wrapper), FALSE); stage_manager = clutter_stage_manager_get_default (); klass = CLUTTER_BACKEND_GET_CLASS (backend); if (klass->create_stage) stage = klass->create_stage (backend, wrapper, error); if (!stage) return NULL; g_assert (CLUTTER_IS_STAGE_WINDOW (stage)); _clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage)); _clutter_stage_manager_add_stage (stage_manager, wrapper); return stage; }
static ClutterStageWindow * clutter_backend_real_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error) { ClutterBackendClass *klass; if (!clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE)) { ClutterStageManager *manager = clutter_stage_manager_get_default (); if (clutter_stage_manager_get_default_stage (manager) != NULL) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, _("The backend of type '%s' does not support " "creating multiple stages"), G_OBJECT_TYPE_NAME (backend)); return NULL; } } klass = CLUTTER_BACKEND_GET_CLASS (backend); g_assert (klass->stage_window_type != G_TYPE_INVALID); return g_object_new (klass->stage_window_type, "backend", backend, "wrapper", wrapper, NULL); }
/** * clutter_win32_get_stage_from_window: * @hwnd: a window handle * * Gets the stage for a particular window. * * Return value: The stage or NULL if a stage does not exist for the * window. * * Since: 0.8 */ ClutterStage * clutter_win32_get_stage_from_window (HWND hwnd) { /* Check whether the window handle is an instance of the stage window class */ if ((ATOM) GetClassLongPtrW (hwnd, GCW_ATOM) == clutter_stage_win32_get_window_class ()) /* If it is there should be a pointer to the stage in the window extra data */ return CLUTTER_STAGE_WIN32 (GetWindowLongPtrW (hwnd, 0))->wrapper; else { /* Otherwise it might be a foreign window so we should check the stage list */ ClutterStageManager *stage_manager; const GSList *stages, *l; stage_manager = clutter_stage_manager_get_default (); stages = clutter_stage_manager_peek_stages (stage_manager); for (l = stages; l != NULL; l = l->next) { ClutterStage *stage = l->data; ClutterStageWindow *impl; impl = _clutter_stage_get_window (stage); g_assert (CLUTTER_IS_STAGE_WIN32 (impl)); if (CLUTTER_STAGE_WIN32 (impl)->hwnd == hwnd) return stage; } } return NULL; }
static gboolean clutter_clock_prepare (GSource *source, gint *timeout) { ClutterClockSource *clock_source = (ClutterClockSource *) source; ClutterMasterClockDefault *master_clock = clock_source->master_clock; int delay; _clutter_threads_acquire_lock (); if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_CONTINUOUS_REDRAW)) { ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); const GSList *stages, *l; stages = clutter_stage_manager_peek_stages (stage_manager); /* Queue a full redraw on all of the stages */ for (l = stages; l != NULL; l = l->next) clutter_actor_queue_redraw (l->data); } delay = master_clock_next_frame_delay (master_clock); _clutter_threads_release_lock (); *timeout = delay; return delay == 0; }
static GSList * master_clock_list_ready_stages (ClutterMasterClockDefault *master_clock) { ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); const GSList *stages, *l; GSList *result; stages = clutter_stage_manager_peek_stages (stage_manager); result = NULL; for (l = stages; l != NULL; l = l->next) { gint64 update_time = _clutter_stage_get_update_time (l->data); /* We carefully avoid to update stages that aren't mapped, because * they have nothing to render and this could cause a deadlock with * some of the SwapBuffers implementations (in particular * GLX_INTEL_swap_event is not emitted if nothing was rendered). * * Also, if a stage has a swap-buffers pending we don't want to draw * to it in case the driver may block the CPU while it waits for the * next backbuffer to become available. * * TODO: We should be able to identify if we are running triple or N * buffered and in these cases we can still draw if there is 1 swap * pending so we can hopefully always be ready to swap for the next * vblank and really match the vsync frequency. */ if (clutter_actor_is_mapped (l->data) && update_time != -1 && update_time <= master_clock->cur_tick) result = g_slist_prepend (result, g_object_ref (l->data)); } return g_slist_reverse (result); }
static gint master_clock_get_swap_wait_time (ClutterMasterClockDefault *master_clock) { ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); const GSList *stages, *l; gint64 min_update_time = -1; stages = clutter_stage_manager_peek_stages (stage_manager); for (l = stages; l != NULL; l = l->next) { gint64 update_time = _clutter_stage_get_update_time (l->data); if (min_update_time == -1 || (update_time != -1 && update_time < min_update_time)) min_update_time = update_time; } if (min_update_time == -1) { return -1; } else { gint64 now = g_source_get_time (master_clock->source); if (min_update_time < now) { return 0; } else { gint64 delay_us = min_update_time - now; return (delay_us + 999) / 1000; } } }
/* * master_clock_is_running: * @master_clock: a #ClutterMasterClock * * Checks if we should currently be advancing timelines or redrawing * stages. * * Return value: %TRUE if the #ClutterMasterClock has at least * one running timeline */ static gboolean master_clock_is_running (ClutterMasterClockDefault *master_clock) { ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); const GSList *stages, *l; stages = clutter_stage_manager_peek_stages (stage_manager); if (master_clock->paused) return FALSE; if (master_clock->timelines) return TRUE; for (l = stages; l; l = l->next) { if (clutter_actor_is_mapped (l->data) && (_clutter_stage_has_queued_events (l->data) || _clutter_stage_needs_update (l->data))) return TRUE; } if (master_clock->ensure_next_iteration) { master_clock->ensure_next_iteration = FALSE; return TRUE; } return FALSE; }
static void clutter_backend_win32_dispose (GObject *gobject) { ClutterBackend *backend = CLUTTER_BACKEND (gobject); ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (gobject); ClutterStageManager *stage_manager; CLUTTER_NOTE (BACKEND, "Disposing the of stages"); stage_manager = clutter_stage_manager_get_default (); g_object_unref (stage_manager); CLUTTER_NOTE (BACKEND, "Removing the event source"); _clutter_backend_win32_events_uninit (CLUTTER_BACKEND (backend_win32)); /* Unrealize all shaders, since the GL context is going away */ _clutter_shader_release_all (); G_OBJECT_CLASS (clutter_backend_win32_parent_class)->dispose (gobject); if (backend->cogl_context) { cogl_object_unref (backend->cogl_context); backend->cogl_context = NULL; } }
static void master_clock_schedule_stage_updates (ClutterMasterClockDefault *master_clock) { ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); const GSList *stages, *l; stages = clutter_stage_manager_peek_stages (stage_manager); for (l = stages; l != NULL; l = l->next) _clutter_stage_schedule_update (l->data); }
/* * master_clock_is_running: * @master_clock: a #ClutterMasterClock * * Checks if we should currently be advancing timelines or redrawing * stages. * * Return value: %TRUE if the #ClutterMasterClock has at least * one running timeline */ static gboolean master_clock_is_running (ClutterMasterClock *master_clock) { ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); const GSList *stages, *l; gboolean stage_free = FALSE; stages = clutter_stage_manager_peek_stages (stage_manager); /* If all of the stages are busy waiting for a swap-buffers to complete * then we stop the master clock... */ for (l = stages; l != NULL; l = l->next) { if (_clutter_stage_get_pending_swaps (l->data) == 0) { stage_free = TRUE; break; } } if (!stage_free) return FALSE; if (master_clock->timelines) return TRUE; for (l = stages; l; l = l->next) { if (_clutter_stage_has_queued_events (l->data) || _clutter_stage_needs_update (l->data)) return TRUE; } if (master_clock->ensure_next_iteration) { master_clock->ensure_next_iteration = FALSE; return TRUE; } return FALSE; }
/** * mpl_panel_clutter_init_with_gtk: * @argc: (inout): a pointer to the number of command line arguments * @argv: (array length=argc) (inout) (allow-none): a pointer to the array * of command line arguments * * Initialializes the libdawati-panel library when used in a Clutter-based * panel that also use Gtk (panels that only use Clutter should use * mpl_panel_clutter_init_lib() instead). * * This function calls gtk_init() and clutter_init(). */ void mpl_panel_clutter_init_with_gtk (gint *argc, gchar ***argv) { ClutterStageManager *manager; gtk_init (argc, argv); clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); clutter_x11_disable_event_retrieval (); if (CLUTTER_INIT_SUCCESS != clutter_init (argc, argv)) { g_error ("Unable to initialize Clutter.\n"); } manager = clutter_stage_manager_get_default (); g_signal_connect_after (manager, "stage-added", G_CALLBACK (_stage_added), NULL); mpl_panel_clutter_load_base_style (); }
static void mex_lirc_do_event (ClutterEvent *event) { const GSList *s; ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); const GSList *stages = clutter_stage_manager_peek_stages (stage_manager); /* FIXME: We should probably check if the stage has focus via X */ for (s = stages; s; s = s->next) { ClutterStage *stage = s->data; ClutterActor *actor = clutter_stage_get_key_focus (stage); if (!actor) continue; event->any.stage = stage; event->any.source = actor; clutter_do_event (event); } }
/* Quit application depending on daemon mode and force parameter */ static void _xfdashboard_application_quit(XfdashboardApplication *self, gboolean inForceQuit) { XfdashboardApplicationPrivate *priv; gboolean shouldQuit; GSList *stages, *entry; g_return_if_fail(XFDASHBOARD_IS_APPLICATION(self)); priv=self->priv; shouldQuit=FALSE; /* Check if we should really quit this instance */ if(inForceQuit==TRUE || priv->isDaemon==FALSE) shouldQuit=TRUE; /* Do nothing if application is already quitting. This can happen if * application is running in daemon mode (primary instance) and another * instance was called with "quit" or "restart" parameter which would * cause this function to be called twice. */ if(priv->isQuitting) return; /* If application is not in daemon mode or if forced is set to TRUE * destroy all stage windows ... */ if(shouldQuit==TRUE) { /* Set flag that application is going to quit */ priv->isQuitting=TRUE; /* If application is told to quit, set the restart style to something * where it won't restart itself. */ if(priv->sessionManagementClient && XFCE_IS_SM_CLIENT(priv->sessionManagementClient)) { xfce_sm_client_set_restart_style(priv->sessionManagementClient, XFCE_SM_CLIENT_RESTART_NORMAL); } /* Destroy stages */ stages=clutter_stage_manager_list_stages(clutter_stage_manager_get_default()); for(entry=stages; entry!=NULL; entry=g_slist_next(entry)) clutter_actor_destroy(CLUTTER_ACTOR(entry->data)); g_slist_free(stages); /* Emit "quit" signal */ g_signal_emit(self, XfdashboardApplicationSignals[SIGNAL_QUIT], 0); /* Really quit application here and now */ if(priv->inited) clutter_main_quit(); } /* ... otherwise emit "suspend" signal */ else { /* Only send signal if not suspended already */ if(!priv->isSuspended) { /* Send signal */ g_signal_emit(self, XfdashboardApplicationSignals[SIGNAL_SUSPEND], 0); /* Set flag for suspension */ priv->isSuspended=TRUE; g_object_notify_by_pspec(G_OBJECT(self), XfdashboardApplicationProperties[PROP_SUSPENDED]); } } }
/** * xfdashboard_notify: * @inSender: The sending #ClutterActor or %NULL * @inIconName: The icon name to display in notification or %NULL * @inFormat: A standard printf() format string for notification text * @...: The parameters to insert into the format string * * Shows a notification with the formatted text as specified in @inFormat * and the parameters at the monitor where the sending actor @inSender * is placed on. * * If @inSender is NULL the primary monitor is used. * * If @inIconName is NULL no icon will be shown in notification. */ void xfdashboard_notify(ClutterActor *inSender, const gchar *inIconName, const gchar *inFormat, ...) { XfdashboardStage *stage; ClutterStageManager *stageManager; va_list args; gchar *text; g_return_if_fail(inSender==NULL || CLUTTER_IS_ACTOR(inSender)); stage=NULL; /* Build text to display */ va_start(args, inFormat); text=g_strdup_vprintf(inFormat, args); va_end(args); /* Get stage of sending actor if available */ if(inSender) stage=XFDASHBOARD_STAGE(clutter_actor_get_stage(inSender)); /* No sending actor specified or no stage found so get default stage */ if(!stage) { const GSList *stages; const GSList *stagesIter; ClutterActorIter interfaceIter; ClutterActor *child; XfdashboardWindowTrackerMonitor *stageMonitor; /* Get stage manager to iterate through stages to find the one * for primary monitor or at least the first stage. */ stageManager=clutter_stage_manager_get_default(); /* Find stage for primary monitor and if we cannot find it * use first stage. */ if(stageManager && CLUTTER_IS_STAGE_MANAGER(stageManager)) { /* Get list of all stages */ stages=clutter_stage_manager_peek_stages(stageManager); /* Iterate through list of all stage and lookup the one for * primary monitor. */ for(stagesIter=stages; stagesIter && !stage; stagesIter=stagesIter->next) { /* Skip this stage if it is not a XfdashboardStage */ if(!XFDASHBOARD_IS_STAGE(stagesIter->data)) continue; /* Iterate through stage's children and lookup stage interfaces */ clutter_actor_iter_init(&interfaceIter, CLUTTER_ACTOR(stagesIter->data)); while(clutter_actor_iter_next(&interfaceIter, &child)) { if(XFDASHBOARD_IS_STAGE_INTERFACE(child)) { stageMonitor=xfdashboard_stage_interface_get_monitor(XFDASHBOARD_STAGE_INTERFACE(child)); if(xfdashboard_window_tracker_monitor_is_primary(stageMonitor)) { stage=XFDASHBOARD_STAGE(clutter_actor_get_stage(child)); } } } } /* If we did not get stage for primary monitor use first stage */ if(!stage && stages) { stage=XFDASHBOARD_STAGE(stages->data); } } /* If we still do not have found a stage to show notification * stop further processing and show notification text as a critical * warning in addition to the critical warning that we could not * find any stage. */ if(!stage) { g_critical(_("Could find any stage to show notification: %s"), text); } } /* Show notification on stage (if any found) */ if(stage) xfdashboard_stage_show_notification(stage, inIconName, text); /* Release allocated resources */ g_free(text); }
static gboolean clutter_clock_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { ClutterClockSource *clock_source = (ClutterClockSource *) source; ClutterMasterClock *master_clock = clock_source->master_clock; ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); gboolean stages_updated = FALSE; GSList *stages, *l; CLUTTER_STATIC_TIMER (master_dispatch_timer, "Mainloop", "Master Clock", "Master clock dispatch", 0); CLUTTER_STATIC_TIMER (master_event_process, "Master Clock", "Event Processing", "The time spent processing events on all stages", 0); CLUTTER_TIMER_START (_clutter_uprof_context, master_dispatch_timer); CLUTTER_NOTE (SCHEDULER, "Master clock [tick]"); clutter_threads_enter (); /* Get the time to use for this frame */ #if GLIB_CHECK_VERSION (2, 27, 3) master_clock->cur_tick = g_source_get_time (source); #else { GTimeVal source_time; g_source_get_current_time (source, &source_time); master_clock->cur_tick = source_time.tv_sec * 1000000L + source_time.tv_usec; } #endif /* We need to protect ourselves against stages being destroyed during * event handling */ stages = clutter_stage_manager_list_stages (stage_manager); g_slist_foreach (stages, (GFunc) g_object_ref, NULL); CLUTTER_TIMER_START (_clutter_uprof_context, master_event_process); master_clock->idle = FALSE; /* Process queued events */ for (l = stages; l != NULL; l = l->next) { /* NB: If a stage is busy waiting for a swap-buffers completion then * we don't process its events so we can maximize the benefits of * motion compression, and avoid multiple picks per frame. */ if (_clutter_stage_get_pending_swaps (l->data) == 0) _clutter_stage_process_queued_events (l->data); } CLUTTER_TIMER_STOP (_clutter_uprof_context, master_event_process); _clutter_master_clock_advance (master_clock); _clutter_run_repaint_functions (); /* Update any stage that needs redraw/relayout after the clock * is advanced. */ for (l = stages; l != NULL; l = l->next) { /* If a stage has a swap-buffers pending we don't want to draw to it * in case the driver may block the CPU while it waits for the next * backbuffer to become available. * * TODO: We should be able to identify if we are running triple or N * buffered and in these cases we can still draw if there is 1 swap * pending so we can hopefully always be ready to swap for the next * vblank and really match the vsync frequency. */ if (_clutter_stage_get_pending_swaps (l->data) == 0) stages_updated |= _clutter_stage_do_update (l->data); } /* The master clock goes idle if no stages were updated and falls back * to polling for timeline progressions... */ if (!stages_updated) master_clock->idle = TRUE; g_slist_foreach (stages, (GFunc) g_object_unref, NULL); g_slist_free (stages); master_clock->prev_tick = master_clock->cur_tick; clutter_threads_leave (); CLUTTER_TIMER_STOP (_clutter_uprof_context, master_dispatch_timer); return TRUE; }