static void on_gesture_end(ClutterGestureAction *action, ClutterActor *stage, gpointer data) { ClutterActor *new_actor, *texture, *actor; gfloat x, y, w, h; GError *error = NULL; GdkColor color; guint16 alpha; gint iw = 125; gint ih = 126; gboolean repeat_x = FALSE; gboolean repeat_y = TRUE; guint bgr; new_actor = tmpRect; gtk_color_button_get_color(GTK_COLOR_BUTTON(app.colorpicker), &color); alpha = gtk_color_button_get_alpha(GTK_COLOR_BUTTON(app.colorpicker)); ClutterColor col = { CLAMP(((color.red / 65535.0) * 255), 0, 255), CLAMP(((color.green / 65535.0) * 255), 0, 255), CLAMP(((color.blue / 65535.0) * 255), 0, 255), CLAMP(((alpha / 65535.0) * 255), 0, 255), }; clutter_rectangle_set_color(CLUTTER_RECTANGLE(new_actor), &col); clutter_rectangle_set_border_width(CLUTTER_RECTANGLE(new_actor), 0); tmpRect = NULL; clutter_actor_get_position(new_actor, &x, &y); clutter_actor_get_size(new_actor, &w, &h); if (background_image_file != NULL){ texture = clutter_texture_new_from_file(background_image_file, &error); if (error != NULL){ g_print("Loading image failed\n"); g_error_free(error); } clutter_actor_set_position(texture, x, y); clutter_actor_set_size(texture, w, h); clutter_actor_add_child(stage, texture); clutter_actor_show(texture); bgr = gtk_combo_box_get_active(GTK_COMBO_BOX(app.background_repeat_select)); switch (bgr){ case 0: repeat_x = repeat_y = FALSE; break; case 1: repeat_x = TRUE; repeat_y = FALSE; break; case 2: repeat_x = FALSE; repeat_y = TRUE; break; case 3: repeat_x = repeat_y = TRUE; break; } clutter_texture_get_base_size(CLUTTER_TEXTURE(texture), &iw, &ih); clutter_actor_set_clip(texture, 0, 0, repeat_x ? w : iw, repeat_y ? h : ih); clutter_texture_set_sync_size(CLUTTER_TEXTURE(texture), TRUE); clutter_texture_set_repeat(CLUTTER_TEXTURE(texture), TRUE, TRUE); clutter_texture_set_keep_aspect_ratio(CLUTTER_TEXTURE(texture), TRUE); actor = texture; clutter_actor_destroy(new_actor); } else { actor = new_actor; } tool = TOOL_SELECT; clutter_actor_add_action(actor, clutter_drag_action_new()); clutter_actor_set_reactive(actor, TRUE); actors = g_list_append(actors, actor); GdkWindow *gdk_window; gdk_window = gtk_widget_get_window(app.stage); gdk_window_set_cursor(gdk_window, NULL); }
static gboolean clutter_stage_glx_realize (ClutterStageWindow *stage_window) { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window); ClutterBackend *backend; ClutterBackendGLX *backend_glx; ClutterBackendX11 *backend_x11; GError *error; CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]", G_OBJECT_TYPE_NAME (stage_window), stage_window); backend = clutter_get_default_backend (); backend_glx = CLUTTER_BACKEND_GLX (backend); backend_x11 = CLUTTER_BACKEND_X11 (backend); if (stage_x11->xwin == None) { XSetWindowAttributes xattr; unsigned long mask; XVisualInfo *xvisinfo; gfloat width, height; CLUTTER_NOTE (MISC, "Creating stage X window"); xvisinfo = clutter_backend_x11_get_visual_info (backend_x11); if (xvisinfo == NULL) { g_critical ("Unable to find suitable GL visual."); return FALSE; } /* window attributes */ xattr.background_pixel = WhitePixel (backend_x11->xdpy, backend_x11->xscreen_num); xattr.border_pixel = 0; xattr.colormap = XCreateColormap (backend_x11->xdpy, backend_x11->xwin_root, xvisinfo->visual, AllocNone); mask = CWBorderPixel | CWColormap; /* Call get_size - this will either get the geometry size (which * before we create the window is set to 640x480), or if a size * is set, it will get that. This lets you set a size on the * stage before it's realized. */ clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height); stage_x11->xwin_width = (gint)width; stage_x11->xwin_height = (gint)height; stage_x11->xwin = XCreateWindow (backend_x11->xdpy, backend_x11->xwin_root, 0, 0, stage_x11->xwin_width, stage_x11->xwin_height, 0, xvisinfo->depth, InputOutput, xvisinfo->visual, mask, &xattr); CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x, size: %dx%d", stage_window, (unsigned int) stage_x11->xwin, stage_x11->xwin_width, stage_x11->xwin_height); XFree (xvisinfo); } if (stage_glx->glxwin == None) { int major; int minor; GLXFBConfig config; /* Try and create a GLXWindow to use with extensions dependent on * GLX versions >= 1.3 that don't accept regular X Windows as GLX * drawables. */ if (glXQueryVersion (backend_x11->xdpy, &major, &minor) && major == 1 && minor >= 3 && _clutter_backend_glx_get_fbconfig (backend_glx, &config)) { stage_glx->glxwin = glXCreateWindow (backend_x11->xdpy, config, stage_x11->xwin, NULL); } } if (clutter_x11_has_event_retrieval ()) { if (clutter_x11_has_xinput ()) { XSelectInput (backend_x11->xdpy, stage_x11->xwin, StructureNotifyMask | FocusChangeMask | ExposureMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask); #ifdef HAVE_XINPUT _clutter_x11_select_events (stage_x11->xwin); #endif } else XSelectInput (backend_x11->xdpy, stage_x11->xwin, StructureNotifyMask | FocusChangeMask | ExposureMask | PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask); #ifdef GLX_INTEL_swap_event if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)) { GLXDrawable drawable = stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin; glXSelectEvent (backend_x11->xdpy, drawable, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); } #endif /* GLX_INTEL_swap_event */ } /* no user resize.. */ clutter_stage_x11_fix_window_size (stage_x11, stage_x11->xwin_width, stage_x11->xwin_height); clutter_stage_x11_set_wm_protocols (stage_x11); /* ask for a context; a no-op, if a context already exists */ error = NULL; _clutter_backend_create_context (backend, &error); if (error) { g_critical ("Unable to realize stage: %s", error->message); g_error_free (error); return FALSE; } CLUTTER_NOTE (BACKEND, "Successfully realized stage"); /* chain up to the StageX11 implementation */ return clutter_stage_glx_parent_iface->realize (stage_window); }
/** * clutter_win32_handle_event: * @msg: A pointer to a structure describing a Win32 message. * * This function processes a single Win32 message. It can be used to * hook into external windows message processing (for example, a GDK * filter function). * * If clutter_win32_disable_event_retrieval() has been called, you must * let this function process events to update Clutter's internal state. * * Return value: %TRUE if the message was handled entirely by Clutter * and no further processing (such as calling the default window * procedure) should take place. %FALSE is returned if is the message * was not handled at all or if Clutter expects processing to take * place. * * Since: 1.6 */ gboolean clutter_win32_handle_event (const MSG *msg) { ClutterBackendWin32 *backend_win32; ClutterStageWin32 *stage_win32; ClutterDeviceManager *manager; ClutterInputDevice *core_pointer, *core_keyboard; ClutterStage *stage; ClutterStageWindow *impl; gboolean return_value = FALSE; stage = clutter_win32_get_stage_from_window (msg->hwnd); /* Ignore any messages for windows which we don't have a stage for */ if (stage == NULL) return FALSE; impl = _clutter_stage_get_window (stage); stage_win32 = CLUTTER_STAGE_WIN32 (impl); backend_win32 = stage_win32->backend; manager = clutter_device_manager_get_default (); core_pointer = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE); core_keyboard = clutter_device_manager_get_core_device (manager, CLUTTER_KEYBOARD_DEVICE); switch (msg->message) { case WM_SIZE: if (!stage_win32->is_foreign_win /* Ignore size changes resulting from the stage being minimized - otherwise the window size will be set to 0,0 */ && msg->wParam != SIZE_MINIMIZED) { WORD new_width = LOWORD (msg->lParam); WORD new_height = HIWORD (msg->lParam); gfloat old_width, old_height; clutter_actor_get_size (CLUTTER_ACTOR (stage), &old_width, &old_height); if (new_width != old_width || new_height != old_height) clutter_actor_set_size (CLUTTER_ACTOR (stage), new_width, new_height); } break; case WM_SHOWWINDOW: if (msg->wParam) clutter_stage_win32_map (stage_win32); else clutter_stage_win32_unmap (stage_win32); break; case WM_ACTIVATE: if (msg->wParam == WA_INACTIVE) { if (stage_win32->state & CLUTTER_STAGE_STATE_ACTIVATED) { ClutterEvent *event = clutter_event_new (CLUTTER_STAGE_STATE); stage_win32->state &= ~CLUTTER_STAGE_STATE_ACTIVATED; event->any.stage = stage; event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED; event->stage_state.new_state = stage_win32->state; take_and_queue_event (event); } } else if (!(stage_win32->state & CLUTTER_STAGE_STATE_ACTIVATED)) { ClutterEvent *event = clutter_event_new (CLUTTER_STAGE_STATE); stage_win32->state |= CLUTTER_STAGE_STATE_ACTIVATED; event->any.stage = stage; event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED; event->stage_state.new_state = stage_win32->state; take_and_queue_event (event); } break; case WM_PAINT: CLUTTER_NOTE (MULTISTAGE, "expose for stage:%p, redrawing", stage); clutter_redraw (stage); break; case WM_DESTROY: { ClutterEvent *event = clutter_event_new (CLUTTER_DESTROY_NOTIFY); CLUTTER_NOTE (EVENT, "WM_DESTROY"); event->any.stage = stage; take_and_queue_event (event); } break; case WM_CLOSE: { ClutterEvent *event = clutter_event_new (CLUTTER_DELETE); CLUTTER_NOTE (EVENT, "WM_CLOSE"); event->any.stage = stage; take_and_queue_event (event); /* The default window proc will destroy the window so we want to prevent this to allow applications to optionally destroy the window themselves */ return_value = TRUE; } break; case WM_LBUTTONDOWN: make_button_event (msg, stage, 1, 1, FALSE, core_pointer); break; case WM_MBUTTONDOWN: make_button_event (msg, stage, 2, 1, FALSE, core_pointer); break; case WM_RBUTTONDOWN: make_button_event (msg, stage, 3, 1, FALSE, core_pointer); break; case WM_LBUTTONUP: make_button_event (msg, stage, 1, 1, TRUE, core_pointer); break; case WM_MBUTTONUP: make_button_event (msg, stage, 2, 1, TRUE, core_pointer); break; case WM_RBUTTONUP: make_button_event (msg, stage, 3, 1, TRUE, core_pointer); break; case WM_LBUTTONDBLCLK: make_button_event (msg, stage, 1, 2, FALSE, core_pointer); break; case WM_MBUTTONDBLCLK: make_button_event (msg, stage, 2, 2, FALSE, core_pointer); break; case WM_RBUTTONDBLCLK: make_button_event (msg, stage, 3, 2, FALSE, core_pointer); break; case WM_MOUSEWHEEL: stage_win32->scroll_pos += (SHORT) HIWORD (msg->wParam); while (abs (stage_win32->scroll_pos) >= WHEEL_DELTA) { ClutterEvent *event = clutter_event_new (CLUTTER_SCROLL); POINT pt; event->scroll.time = msg->time; event->scroll.modifier_state = get_modifier_state (LOWORD (msg->wParam)); event->any.stage = stage; clutter_event_set_device (event, core_pointer); /* conversion to window coordinates is required */ pt.x = GET_X_LPARAM (msg->lParam); pt.y = GET_Y_LPARAM (msg->lParam); ScreenToClient (msg->hwnd, &pt); event->scroll.x = pt.x; event->scroll.y = pt.y; if (stage_win32->scroll_pos > 0) { event->scroll.direction = CLUTTER_SCROLL_UP; stage_win32->scroll_pos -= WHEEL_DELTA; } else { event->scroll.direction = CLUTTER_SCROLL_DOWN; stage_win32->scroll_pos += WHEEL_DELTA; } take_and_queue_event (event); } break; case WM_MOUSEMOVE: { ClutterEvent *event = clutter_event_new (CLUTTER_MOTION); event->motion.time = msg->time; event->motion.x = GET_X_LPARAM (msg->lParam); event->motion.y = GET_Y_LPARAM (msg->lParam); event->motion.modifier_state = get_modifier_state (msg->wParam); event->any.stage = stage; clutter_event_set_device (event, core_pointer); /* We need to start tracking when the mouse enters the stage if we're not already */ if (!stage_win32->tracking_mouse) { ClutterEvent *crossing = clutter_event_new (CLUTTER_ENTER); TRACKMOUSEEVENT tmevent; tmevent.cbSize = sizeof (tmevent); tmevent.dwFlags = TME_LEAVE; tmevent.hwndTrack = stage_win32->hwnd; TrackMouseEvent (&tmevent); event->crossing.time = msg->time; event->crossing.x = event->motion.x; event->crossing.y = event->motion.y; event->crossing.stage = stage; event->crossing.source = CLUTTER_ACTOR (stage); event->crossing.related = NULL; clutter_event_set_device (event, core_pointer); /* we entered the stage */ _clutter_stage_add_device (stage, event->crossing.device); take_and_queue_event (crossing); stage_win32->tracking_mouse = TRUE; } take_and_queue_event (event); } break; case WM_MOUSELEAVE: { ClutterEvent *event = clutter_event_new (CLUTTER_LEAVE); event->crossing.time = msg->time; event->crossing.x = msg->pt.x; event->crossing.y = msg->pt.y; event->crossing.stage = stage; event->crossing.source = CLUTTER_ACTOR (stage); event->crossing.related = NULL; clutter_event_set_device (event, core_pointer); /* we left the stage */ _clutter_stage_remove_device (stage, core_pointer); /* When we get a leave message the mouse tracking is automatically cancelled so we'll need to start it again when the mouse next enters the window */ stage_win32->tracking_mouse = FALSE; take_and_queue_event (event); } break; case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: { ClutterEvent *event = clutter_event_new (CLUTTER_EVENT_NONE); int scan_code = (msg->lParam >> 16) & 0xff; int min = 0, max = CLUTTER_WIN32_KEY_MAP_SIZE, mid; BYTE key_states[256]; /* Get the keyboard modifier states. GetKeyboardState conveniently gets the key state that was current when the last keyboard message read was generated */ GetKeyboardState(key_states); /* Binary chop to check if we have a direct mapping for this key code */ while (min < max) { mid = (min + max) / 2; if (clutter_win32_key_map[mid].win_sym == msg->wParam) { event->key.keyval = clutter_win32_key_map[mid].clutter_sym; event->key.unicode_value = 0; break; } else if (clutter_win32_key_map[mid].win_sym < msg->wParam) min = mid + 1; else max = mid; } /* If we don't have a direct mapping then try getting the unicode value of the key sym */ if (min >= max) { WCHAR ch; BYTE shift_state[256]; /* Translate to a Unicode value, but only take into account the shift key. That way Ctrl+Shift+C will generate a capital C virtual key code with a zero unicode value for example */ memset (shift_state, 0, 256); shift_state[VK_SHIFT] = key_states[VK_SHIFT]; shift_state[VK_LSHIFT] = key_states[VK_LSHIFT]; shift_state[VK_RSHIFT] = key_states[VK_RSHIFT]; shift_state[VK_CAPITAL] = key_states[VK_CAPITAL]; if (ToUnicode (msg->wParam, scan_code, shift_state, &ch, 1, 0) == 1 /* The codes in this range directly match the Latin 1 codes so we can just use the Unicode value as the key sym */ && ch >= 0x20 && ch <= 0xff) event->key.keyval = ch; else /* Otherwise we don't know what the key means but the application might be able to do something with the scan code so we might as well still generate the event */ event->key.keyval = CLUTTER_KEY_VoidSymbol; /* Get the unicode value of the keypress again using the full modifier state */ if (ToUnicode (msg->wParam, scan_code, key_states, &ch, 1, 0) == 1) event->key.unicode_value = ch; else event->key.unicode_value = 0; } event->key.type = msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN ? CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE; event->key.time = msg->time; event->key.modifier_state = get_key_modifier_state (key_states); event->key.hardware_keycode = scan_code; event->any.stage = stage; clutter_event_set_device (event, core_keyboard); take_and_queue_event (event); } break; case WM_GETMINMAXINFO: { MINMAXINFO *min_max_info = (MINMAXINFO *) msg->lParam; _clutter_stage_win32_get_min_max_info (stage_win32, min_max_info); return_value = TRUE; } break; case WM_SETCURSOR: /* If the cursor is in the window's client area and the stage's cursor should be invisible then we'll set a blank cursor instead */ if (LOWORD (msg->lParam) == HTCLIENT && !stage_win32->is_cursor_visible) { return_value = TRUE; _clutter_stage_win32_update_cursor (stage_win32); } break; } return return_value; }
static void clutter_snap_constraint_update_allocation (ClutterConstraint *constraint, ClutterActor *actor, ClutterActorBox *allocation) { ClutterSnapConstraint *self = CLUTTER_SNAP_CONSTRAINT (constraint); gfloat source_width, source_height; gfloat source_x, source_y; gfloat actor_width, actor_height; if (self->source == NULL) return; clutter_actor_get_position (self->source, &source_x, &source_y); clutter_actor_get_size (self->source, &source_width, &source_height); clutter_actor_box_get_size (allocation, &actor_width, &actor_height); switch (self->to_edge) { case CLUTTER_SNAP_EDGE_LEFT: if (self->from_edge == CLUTTER_SNAP_EDGE_LEFT) allocation->x1 = source_x + self->offset; else if (self->from_edge == CLUTTER_SNAP_EDGE_RIGHT) allocation->x2 = source_x + self->offset; else warn_horizontal_edge ("left", self->actor, self->source); break; case CLUTTER_SNAP_EDGE_RIGHT: if (self->from_edge == CLUTTER_SNAP_EDGE_RIGHT) allocation->x2 = source_x + source_height + self->offset; else if (self->from_edge == CLUTTER_SNAP_EDGE_LEFT) allocation->x1 = source_x + source_height + self->offset; else warn_horizontal_edge ("right", self->actor, self->source); break; break; case CLUTTER_SNAP_EDGE_TOP: if (self->from_edge == CLUTTER_SNAP_EDGE_TOP) allocation->y1 = source_y + self->offset; else if (self->from_edge == CLUTTER_SNAP_EDGE_BOTTOM) allocation->y2 = source_y + self->offset; else warn_vertical_edge ("top", self->actor, self->source); break; case CLUTTER_SNAP_EDGE_BOTTOM: if (self->from_edge == CLUTTER_SNAP_EDGE_BOTTOM) allocation->y2 = source_y + source_height + self->offset; else if (self->from_edge == CLUTTER_SNAP_EDGE_TOP) allocation->y1 = source_y + source_height + self->offset; else warn_vertical_edge ("bottom", self->actor, self->source); break; default: g_assert_not_reached (); break; } if (allocation->x2 - allocation->x1 < 0) allocation->x2 = allocation->x1; if (allocation->y2 - allocation->y1 < 0) allocation->y2 = allocation->y1; }
int main (int argc, char *argv[]) { ClutterActor *actor, *stage, *buttons, *button; ChamplainMarkerLayer *layer; ChamplainPathLayer *path; gfloat width, total_width = 0; if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; stage = clutter_stage_new (); clutter_actor_set_size (stage, 800, 600); g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); /* Create the map view */ actor = champlain_view_new (); clutter_actor_set_size (CLUTTER_ACTOR (actor), 800, 600); clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor); /* Create the buttons */ buttons = clutter_group_new (); clutter_actor_set_position (buttons, PADDING, PADDING); button = make_button ("Zoom in"); clutter_container_add_actor (CLUTTER_CONTAINER (buttons), button); clutter_actor_set_reactive (button, TRUE); clutter_actor_get_size (button, &width, NULL); total_width += width + PADDING; g_signal_connect (button, "button-release-event", G_CALLBACK (zoom_in), actor); button = make_button ("Zoom out"); clutter_container_add_actor (CLUTTER_CONTAINER (buttons), button); clutter_actor_set_reactive (button, TRUE); clutter_actor_set_position (button, total_width, 0); clutter_actor_get_size (button, &width, NULL); g_signal_connect (button, "button-release-event", G_CALLBACK (zoom_out), actor); clutter_container_add_actor (CLUTTER_CONTAINER (stage), buttons); /* Create the markers and marker layer */ layer = create_marker_layer (CHAMPLAIN_VIEW (actor), &path); champlain_view_add_layer (CHAMPLAIN_VIEW (actor), CHAMPLAIN_LAYER (layer)); /* Connect to the click event */ clutter_actor_set_reactive (actor, TRUE); g_signal_connect (actor, "button-release-event", G_CALLBACK (map_view_button_release_cb), actor); /* Finish initialising the map view */ g_object_set (G_OBJECT (actor), "zoom-level", 12, "kinetic-mode", TRUE, NULL); champlain_view_center_on (CHAMPLAIN_VIEW (actor), 45.466, -73.75); clutter_actor_show (stage); clutter_main (); return 0; }
static void mnb_fancy_bin_paint (ClutterActor *actor) { MnbFancyBin *self = MNB_FANCY_BIN (actor); MnbFancyBinPrivate *priv = self->priv; /* Draw the clipped child if necessary */ if (priv->fanciness > 0.0) { MxPadding padding; gfloat width, height; clutter_actor_get_size (actor, &width, &height); mx_widget_get_padding (MX_WIDGET (actor), &padding); /* Create a clip path so that the clone won't poke out * from underneath the background. */ cogl_path_new (); cogl_path_move_to (padding.left + priv->curve_radius, padding.top); cogl_path_arc (width - padding.right - priv->curve_radius, priv->curve_radius + padding.top, priv->curve_radius, priv->curve_radius, 270, 360); cogl_path_arc (width - padding.right - priv->curve_radius, height - padding.bottom - priv->curve_radius, priv->curve_radius, priv->curve_radius, 0, 90); cogl_path_arc (padding.left + priv->curve_radius, height - padding.bottom - priv->curve_radius, priv->curve_radius, priv->curve_radius, 90, 180); cogl_path_arc (padding.left + priv->curve_radius, padding.top + priv->curve_radius, priv->curve_radius, priv->curve_radius, 180, 270); cogl_path_close (); cogl_clip_push_from_path (); /* Paint child */ if (priv->child) clutter_actor_paint (priv->child); cogl_clip_pop (); /* Chain up for background */ CLUTTER_ACTOR_CLASS (mnb_fancy_bin_parent_class)->paint (actor); } /* Draw the un-fancy child */ if ((priv->fanciness < 1.0) && priv->clone) clutter_actor_paint (priv->clone); }
static void clutter_reflect_texture_paint (ClutterActor *actor) { ClutterReflectTexturePrivate *priv; ClutterReflectTexture *texture; ClutterClone *clone; ClutterTexture *parent; guint width, height; gfloat fwidth, fheight; gint r_height; gint opacity; gint bottom; CoglHandle cogl_texture; CoglTextureVertex tvert[4]; CoglFixed rty; texture = CLUTTER_REFLECT_TEXTURE (actor); clone = CLUTTER_CLONE (actor); parent = (ClutterTexture*) clutter_clone_get_source (clone); if (!parent) return; if (!CLUTTER_ACTOR_IS_REALIZED (parent)) clutter_actor_realize (CLUTTER_ACTOR (parent)); cogl_texture = clutter_texture_get_cogl_texture (parent); if (cogl_texture == COGL_INVALID_HANDLE) return; priv = texture->priv; clutter_actor_get_size (CLUTTER_ACTOR(parent), &fwidth, &fheight); width = fwidth; height = fheight; if (!height) // probably won't happen, but just in case, to avoid divide by zero. return; r_height = priv->reflection_height; bottom = priv->reflect_bottom; opacity = clutter_actor_get_opacity(actor); if (r_height < 0 || r_height > height) r_height = height; #define FX(x) COGL_FIXED_FROM_INT(x) rty = COGL_FIXED_FAST_DIV(FX(bottom ? height-r_height : r_height),FX(height)); /* clockise vertices and tex coords and colors! */ tvert[0].x = tvert[0].y = tvert[0].z = 0; tvert[0].tx = 0; tvert[0].ty = bottom ? COGL_FIXED_1 : rty; tvert[0].color.red = tvert[0].color.green = tvert[0].color.blue = 0xff; tvert[0].color.alpha = bottom ? opacity : 0; tvert[1].x = FX(width); tvert[1].y = tvert[1].z = 0; tvert[1].tx = COGL_FIXED_1; tvert[1].ty = bottom ? COGL_FIXED_1 : rty; tvert[1].color.red = tvert[1].color.green = tvert[1].color.blue = 0xff; tvert[1].color.alpha = bottom ? opacity : 0; tvert[2].x = FX(width); tvert[2].y = FX(r_height); tvert[2].z = 0; tvert[2].tx = COGL_FIXED_1; tvert[2].ty = bottom ? rty : 0; tvert[2].color.red = tvert[2].color.green = tvert[2].color.blue = 0xff; tvert[2].color.alpha = bottom ? 0 : opacity; tvert[3].x = 0; tvert[3].y = FX(r_height); tvert[3].z = 0; tvert[3].tx = 0; tvert[3].ty = bottom ? rty : 0; tvert[3].color.red = tvert[3].color.green = tvert[3].color.blue = 0xff; tvert[3].color.alpha = bottom ? 0 : opacity; cogl_push_matrix (); cogl_set_source_texture(cogl_texture); /* FIXME: this does not work as expected */ /* cogl_polygon(tvert, 4, TRUE); */ cogl_pop_matrix (); }
static void clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect) { ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect); ClutterDeformEffectPrivate *priv = self->priv; CoglHandle material; CoglPipeline *pipeline; CoglDepthState depth_state; CoglFramebuffer *fb = cogl_get_draw_framebuffer (); if (priv->is_dirty) { ClutterRect rect; gboolean mapped_buffer; CoglVertexP3T2C4 *verts; ClutterActor *actor; gfloat width, height; guint opacity; gint i, j; actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); opacity = clutter_actor_get_paint_opacity (actor); /* if we don't have a target size, fall back to the actor's * allocation, though wrong it might be */ if (clutter_offscreen_effect_get_target_rect (effect, &rect)) { width = clutter_rect_get_width (&rect); height = clutter_rect_get_height (&rect); } else clutter_actor_get_size (actor, &width, &height); /* XXX ideally, the sub-classes should tell us what they * changed in the texture vertices; we then would be able to * avoid resubmitting the same data, if it did not change. for * the time being, we resubmit everything */ verts = cogl_buffer_map (COGL_BUFFER (priv->buffer), COGL_BUFFER_ACCESS_WRITE, COGL_BUFFER_MAP_HINT_DISCARD); /* If the map failed then we'll resort to allocating a temporary buffer */ if (verts == NULL) { mapped_buffer = FALSE; verts = g_malloc (sizeof (*verts) * priv->n_vertices); } else mapped_buffer = TRUE; for (i = 0; i < priv->y_tiles + 1; i++) { for (j = 0; j < priv->x_tiles + 1; j++) { CoglVertexP3T2C4 *vertex_out; CoglTextureVertex vertex; /* CoglTextureVertex isn't an ideal structure to use for this because it contains a CoglColor. The internal layout of CoglColor is mean to be private so Clutter can not pass a pointer to it as a vertex attribute. Also it contains padding so we end up storing more data in the vertex buffer than we need to. Instead we let the application modify a dummy vertex and then copy the details back out to a more well-defined struct */ vertex.tx = (float) j / priv->x_tiles; vertex.ty = (float) i / priv->y_tiles; vertex.x = width * vertex.tx; vertex.y = height * vertex.ty; vertex.z = 0.0f; cogl_color_init_from_4ub (&vertex.color, 255, 255, 255, opacity); clutter_deform_effect_deform_vertex (self, width, height, &vertex); vertex_out = verts + i * (priv->x_tiles + 1) + j; vertex_out->x = vertex.x; vertex_out->y = vertex.y; vertex_out->z = vertex.z; vertex_out->s = vertex.tx; vertex_out->t = vertex.ty; vertex_out->r = cogl_color_get_red_byte (&vertex.color); vertex_out->g = cogl_color_get_green_byte (&vertex.color); vertex_out->b = cogl_color_get_blue_byte (&vertex.color); vertex_out->a = cogl_color_get_alpha_byte (&vertex.color); } } if (mapped_buffer) cogl_buffer_unmap (COGL_BUFFER (priv->buffer)); else { cogl_buffer_set_data (COGL_BUFFER (priv->buffer), 0, /* offset */ verts, sizeof (*verts) * priv->n_vertices); g_free (verts); } priv->is_dirty = FALSE; } material = clutter_offscreen_effect_get_target (effect); pipeline = COGL_PIPELINE (material); /* enable depth testing */ cogl_depth_state_init (&depth_state); cogl_depth_state_set_test_enabled (&depth_state, TRUE); cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL); /* enable backface culling if we have a back material */ if (priv->back_pipeline != NULL) cogl_pipeline_set_cull_face_mode (pipeline, COGL_PIPELINE_CULL_FACE_MODE_BACK); /* draw the front */ if (material != NULL) cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive); /* draw the back */ if (priv->back_pipeline != NULL) { CoglPipeline *back_pipeline; /* We probably shouldn't be modifying the user's material so instead we make a temporary copy */ back_pipeline = cogl_pipeline_copy (priv->back_pipeline); cogl_pipeline_set_depth_state (back_pipeline, &depth_state, NULL); cogl_pipeline_set_cull_face_mode (pipeline, COGL_PIPELINE_CULL_FACE_MODE_FRONT); cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive); cogl_object_unref (back_pipeline); } if (G_UNLIKELY (priv->lines_primitive != NULL)) { CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx); cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0); cogl_framebuffer_draw_primitive (fb, lines_pipeline, priv->lines_primitive); cogl_object_unref (lines_pipeline); } }
/* Get largest minimum and natural size of all visible children * for calculation of one child and returns the number of visible ones */ static gint _xfdashboard_fill_box_layout_get_largest_sizes(XfdashboardFillBoxLayout *self, ClutterContainer *inContainer, gfloat *outMinWidth, gfloat *outNaturalWidth, gfloat *outMinHeight, gfloat *outNaturalHeight) { XfdashboardFillBoxLayoutPrivate *priv; ClutterActor *child; ClutterActorIter iter; gint numberChildren; gfloat largestMinWidth, largestNaturalWidth; gfloat largestMinHeight, largestNaturalHeight; gfloat childMinWidth, childNaturalWidth; gfloat childMinHeight, childNaturalHeight; ClutterActor *parent; gfloat parentWidth, parentHeight; gfloat aspectRatio; g_return_val_if_fail(XFDASHBOARD_IS_FILL_BOX_LAYOUT(self), 0); g_return_val_if_fail(CLUTTER_IS_CONTAINER(inContainer), 0); g_return_val_if_fail(CLUTTER_IS_ACTOR(inContainer), 0); priv=self->priv; /* Iterate through all children and determine sizes */ numberChildren=0; largestMinWidth=largestNaturalWidth=largestMinHeight=largestNaturalHeight=0.0f; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { /* Only check visible children */ if(!clutter_actor_is_visible(child)) continue; /* Check for largest size */ clutter_actor_get_preferred_size(child, &childMinWidth, &childNaturalWidth, &childMinHeight, &childNaturalHeight); if(childMinWidth>largestMinWidth) largestMinWidth=childMinWidth; if(childNaturalWidth>largestNaturalWidth) largestNaturalWidth=childNaturalWidth; if(childMinHeight>largestMinHeight) largestMinHeight=childMinHeight; if(childNaturalHeight>largestNaturalHeight) largestNaturalHeight=childNaturalHeight; /* Count visible children */ numberChildren++; } /* Depending on orientation set sizes to fit into parent actor */ parent=clutter_actor_get_parent(CLUTTER_ACTOR(inContainer)); if(parent) { aspectRatio=1.0f; clutter_actor_get_size(CLUTTER_ACTOR(parent), &parentWidth, &parentHeight); if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { if(priv->keepAspect==TRUE) { aspectRatio=largestMinWidth/largestMinHeight; largestMinHeight=parentHeight; largestMinWidth=largestMinHeight*aspectRatio; aspectRatio=largestNaturalWidth/largestNaturalHeight; largestNaturalHeight=parentHeight; largestNaturalWidth=largestNaturalHeight*aspectRatio; } else { largestMinHeight=parentHeight; largestNaturalHeight=parentHeight; } } else { if(priv->keepAspect==TRUE) { aspectRatio=largestMinHeight/largestMinWidth; largestMinWidth=parentWidth; largestMinHeight=largestMinWidth*aspectRatio; aspectRatio=largestNaturalHeight/largestNaturalWidth; largestNaturalWidth=parentWidth; largestNaturalHeight=largestNaturalWidth*aspectRatio; } else { largestMinWidth=parentWidth; largestNaturalWidth=parentWidth; } } } /* Set return values */ if(outMinWidth) *outMinWidth=largestMinWidth; if(outNaturalWidth) *outNaturalWidth=largestNaturalWidth; if(outMinHeight) *outMinHeight=largestMinHeight; if(outNaturalHeight) *outNaturalHeight=largestNaturalHeight; /* Return number of visible children */ return(numberChildren); }
/** * clutter_gdk_handle_event: * @event: a #GdkEvent * * This function processes a single GDK event; it can be used to hook * into external event processing * * Return value: #GdkFilterReturn. %GDK_FILTER_REMOVE indicates that * Clutter has internally handled the event and the caller should do * no further processing. %GDK_FILTER_CONTINUE indicates that Clutter * is either not interested in the event, or has used the event to * update internal state without taking any exclusive action. * %GDK_FILTER_TRANSLATE will not occur. * */ GdkFilterReturn clutter_gdk_handle_event (GdkEvent *gdk_event) { ClutterDeviceManager *device_manager; ClutterBackendGdk *backend_gdk; ClutterBackend *backend; ClutterStage *stage = NULL; ClutterEvent *event = NULL; gint spin = 0; GdkFilterReturn result = GDK_FILTER_CONTINUE; ClutterInputDevice *device, *source_device; GdkDevice *gdk_device; backend = clutter_get_default_backend (); if (!CLUTTER_IS_BACKEND_GDK (backend)) return GDK_FILTER_CONTINUE; if (gdk_event->any.window == NULL) return GDK_FILTER_CONTINUE; device_manager = clutter_device_manager_get_default (); if (G_UNLIKELY (device_manager == NULL)) return GDK_FILTER_CONTINUE; backend_gdk = CLUTTER_BACKEND_GDK (backend); stage = clutter_gdk_get_stage_from_window (gdk_event->any.window); gdk_device = gdk_event_get_device (gdk_event); if (gdk_device != NULL) device = _clutter_device_manager_gdk_lookup_device (device_manager, gdk_device); else device = NULL; gdk_device = gdk_event_get_source_device (gdk_event); if (gdk_device != NULL) source_device = _clutter_device_manager_gdk_lookup_device (device_manager, gdk_device); else source_device = NULL; if (stage == NULL) return GDK_FILTER_CONTINUE; _clutter_threads_acquire_lock (); switch (gdk_event->type) { case GDK_DELETE: event = clutter_event_new (CLUTTER_DELETE); break; case GDK_DESTROY: event = clutter_event_new (CLUTTER_DESTROY_NOTIFY); break; case GDK_EXPOSE: { ClutterPaintVolume clip; ClutterVertex origin; CLUTTER_NOTE (EVENT, "Expose for stage '%s' [%p] { %d, %d - %d x %d }", _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)), stage, gdk_event->expose.area.x, gdk_event->expose.area.y, gdk_event->expose.area.width, gdk_event->expose.area.height); origin.x = gdk_event->expose.area.x; origin.y = gdk_event->expose.area.y; origin.z = 0; _clutter_paint_volume_init_static (&clip, CLUTTER_ACTOR (stage)); clutter_paint_volume_set_origin (&clip, &origin); clutter_paint_volume_set_width (&clip, gdk_event->expose.area.width); clutter_paint_volume_set_height (&clip, gdk_event->expose.area.height); _clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), 0, &clip); clutter_paint_volume_free (&clip); } break; case GDK_DAMAGE: /* This is handled by cogl */ break; case GDK_MOTION_NOTIFY: event = clutter_event_new (CLUTTER_MOTION); event->motion.time = gdk_event->motion.time; event->motion.x = gdk_event->motion.x; event->motion.y = gdk_event->motion.y; event->motion.axes = NULL; /* It's all X in the end, right? */ event->motion.modifier_state = gdk_event->motion.state; clutter_event_set_device (event, device); clutter_event_set_source_device (event, source_device); CLUTTER_NOTE (EVENT, "Motion notifiy [%.2f, %.2f]", event->motion.x, event->motion.y); break; case GDK_BUTTON_PRESS: case GDK_BUTTON_RELEASE: event = clutter_event_new (gdk_event->type == GDK_BUTTON_PRESS ? CLUTTER_BUTTON_PRESS : CLUTTER_BUTTON_RELEASE); event->button.time = gdk_event->button.time; event->button.x = gdk_event->button.x; event->button.y = gdk_event->button.y; event->button.axes = NULL; event->button.modifier_state = gdk_event->button.state; event->button.button = gdk_event->button.button; event->button.click_count = 1; clutter_event_set_device (event, device); clutter_event_set_source_device (event, source_device); CLUTTER_NOTE (EVENT, "Button %d %s [%.2f, %.2f]", event->button.button, event->type == CLUTTER_BUTTON_PRESS ? "press" : "release", event->button.x, event->button.y); break; case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: /* these are handled by clutter-main.c updating click_count */ break; case GDK_KEY_PRESS: case GDK_KEY_RELEASE: event = clutter_event_new (gdk_event->type == GDK_KEY_PRESS ? CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE); event->key.time = gdk_event->key.time; event->key.modifier_state = gdk_event->key.state; event->key.keyval = gdk_event->key.keyval; event->key.hardware_keycode = gdk_event->key.hardware_keycode; event->key.unicode_value = g_utf8_get_char (gdk_event->key.string); clutter_event_set_device (event, device); clutter_event_set_source_device (event, source_device); CLUTTER_NOTE (EVENT, "Key %d %s", event->key.keyval, event->type == CLUTTER_KEY_PRESS ? "press" : "release"); break; case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: event = clutter_event_new (gdk_event->type == GDK_ENTER_NOTIFY ? CLUTTER_ENTER : CLUTTER_LEAVE); event->crossing.source = CLUTTER_ACTOR (stage); event->crossing.time = gdk_event_get_time (gdk_event); event->crossing.x = gdk_event->crossing.x; event->crossing.y = gdk_event->crossing.y; /* XXX: no better fallback here? */ clutter_event_set_device (event, device); clutter_event_set_source_device (event, source_device); if (gdk_event->type == GDK_ENTER_NOTIFY) _clutter_input_device_set_stage (clutter_event_get_device (event), stage); else _clutter_input_device_set_stage (clutter_event_get_device (event), NULL); CLUTTER_NOTE (EVENT, "Crossing %s [%.2f, %.2f]", event->type == CLUTTER_ENTER ? "enter" : "leave", event->crossing.x, event->crossing.y); break; case GDK_FOCUS_CHANGE: if (gdk_event->focus_change.in) _clutter_stage_update_state (stage, 0, CLUTTER_STAGE_STATE_ACTIVATED); else _clutter_stage_update_state (stage, CLUTTER_STAGE_STATE_ACTIVATED, 0); break; case GDK_CONFIGURE: { gfloat w, h; clutter_actor_get_size (CLUTTER_ACTOR (stage), &w, &h); if (w != gdk_event->configure.width || h != gdk_event->configure.height) { clutter_actor_set_size (CLUTTER_ACTOR (stage), gdk_event->configure.width, gdk_event->configure.height); } } break; case GDK_SCROLL: event = clutter_event_new (CLUTTER_SCROLL); event->scroll.time = gdk_event->scroll.time; event->scroll.x = gdk_event->scroll.x; event->scroll.y = gdk_event->scroll.y; event->scroll.modifier_state = gdk_event->scroll.state; event->scroll.axes = NULL; /* XXX: must keep ClutterScrollDirection compatible with GdkScrollDirection */ event->scroll.direction = (ClutterScrollDirection) gdk_event->scroll.direction; clutter_event_set_device (event, device); clutter_event_set_source_device (event, source_device); clutter_event_set_scroll_delta (event, gdk_event->scroll.delta_x, gdk_event->scroll.delta_y); break; case GDK_WINDOW_STATE: if (gdk_event->window_state.changed_mask & GDK_WINDOW_STATE_FULLSCREEN) { gboolean is_fullscreen; is_fullscreen = (gdk_event->window_state.new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0; if (is_fullscreen) _clutter_stage_update_state (stage, 0, CLUTTER_STAGE_STATE_FULLSCREEN); else _clutter_stage_update_state (stage, CLUTTER_STAGE_STATE_FULLSCREEN, 0); } break; case GDK_SETTING: _clutter_backend_gdk_update_setting (backend_gdk, gdk_event->setting.name); break; default: break; } if (event != NULL) { event->any.stage = stage; if (gdk_event->any.send_event) event->any.flags = CLUTTER_EVENT_FLAG_SYNTHETIC; _clutter_event_push (event, FALSE); spin = 1; CLUTTER_NOTE (EVENT, "Translated one event from Gdk"); /* handle also synthetic enter/leave events */ if (event->type == CLUTTER_MOTION) spin += 2; while (spin > 0 && (event = clutter_event_get ())) { /* forward the event into clutter for emission etc. */ clutter_do_event (event); clutter_event_free (event); --spin; } result = GDK_FILTER_REMOVE; } _clutter_threads_release_lock (); return result; }
/* Re-layout and allocate children of container we manage */ static void _xfdashboard_fill_box_layout_allocate(ClutterLayoutManager *inLayoutManager, ClutterContainer *inContainer, const ClutterActorBox *inAllocation, ClutterAllocationFlags inFlags) { XfdashboardFillBoxLayout *self; XfdashboardFillBoxLayoutPrivate *priv; ClutterActor *child; ClutterActorIter iter; gfloat parentWidth, parentHeight; gfloat homogeneousSize; gfloat x, y, w, h; gfloat aspectRatio; ClutterActorBox childAllocation; g_return_if_fail(XFDASHBOARD_IS_FILL_BOX_LAYOUT(inLayoutManager)); g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer)); self=XFDASHBOARD_FILL_BOX_LAYOUT(inLayoutManager); priv=self->priv; /* Get dimension of allocation */ parentWidth=clutter_actor_box_get_width(inAllocation); parentHeight=clutter_actor_box_get_height(inAllocation); /* If homogeneous determine sizes for all children */ if(priv->isHomogeneous==TRUE) { if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { _xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, NULL, &homogeneousSize, NULL, NULL); } else { _xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, NULL, NULL, NULL, &homogeneousSize); } } /* Iterate through children and set their sizes */ x=y=0.0f; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { /* Only set sizes on visible children */ if(!clutter_actor_is_visible(child)) continue; /* Calculate and set new allocation of child */ if(priv->isHomogeneous==FALSE) { clutter_actor_get_size(CLUTTER_ACTOR(inContainer), &w, &h); if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { aspectRatio=w/h; h=parentHeight; w=h*aspectRatio; } else { aspectRatio=h/w; w=parentWidth; h=w*aspectRatio; } } else { if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { w=homogeneousSize; h=parentHeight; } else { w=parentWidth; h=homogeneousSize; } } /* Set new allocation of child */ childAllocation.x1=ceil(x); childAllocation.y1=ceil(y); childAllocation.x2=ceil(childAllocation.x1+w); childAllocation.y2=ceil(childAllocation.y1+h); clutter_actor_allocate(child, &childAllocation, inFlags); /* Set up for next child */ if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) x+=(w+priv->spacing); else y+=(h+priv->spacing); } }
/* Get minimum and natural size of all visible children */ static void _xfdashboard_fill_box_layout_get_sizes_for_all(XfdashboardFillBoxLayout *self, ClutterContainer *inContainer, gfloat *outMinWidth, gfloat *outNaturalWidth, gfloat *outMinHeight, gfloat *outNaturalHeight) { XfdashboardFillBoxLayoutPrivate *priv; ClutterActor *child; ClutterActorIter iter; gint numberChildren; gfloat minWidth, naturalWidth; gfloat minHeight, naturalHeight; gfloat childMinWidth, childNaturalWidth; gfloat childMinHeight, childNaturalHeight; ClutterActor *parent; gfloat parentWidth, parentHeight; gfloat aspectRatio; g_return_if_fail(XFDASHBOARD_IS_FILL_BOX_LAYOUT(self)); g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer)); g_return_if_fail(CLUTTER_IS_ACTOR(inContainer)); priv=self->priv; /* Initialize return values */ numberChildren=0; minWidth=naturalWidth=minHeight=naturalHeight=0.0f; /* If not homogeneous then iterate through all children and determine sizes ... */ if(priv->isHomogeneous==FALSE) { /* Iterate through children and calculate sizes */ clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { /* Only get sizes of visible children */ if(!clutter_actor_is_visible(child)) continue; /* Count visible children */ numberChildren++; /* Determine sizes of visible child */ clutter_actor_get_preferred_size(child, &childMinWidth, &childNaturalWidth, &childMinHeight, &childNaturalHeight); if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { minWidth+=childMinWidth; naturalWidth+=childNaturalWidth; if(childMinHeight>minHeight) minHeight=childMinHeight; if(childNaturalHeight>naturalHeight) naturalHeight=childNaturalHeight; } else { minHeight+=childMinHeight; naturalHeight+=childNaturalHeight; if(childMinWidth>naturalWidth) minWidth=naturalWidth; if(childNaturalWidth>naturalHeight) naturalHeight=childNaturalWidth; } } } /* ... otherwise get largest minimum and natural size and add spacing */ else { /* Get number of visible children and also largest minimum * and natural size */ numberChildren=_xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, &childMinWidth, &childNaturalWidth, &childMinHeight, &childNaturalHeight); /* Multiply largest sizes with number visible children */ if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { minWidth=(numberChildren*childMinWidth); naturalWidth=(numberChildren*childNaturalWidth); minHeight=childMinHeight; naturalHeight=childNaturalHeight; } else { minWidth=childMinWidth; naturalWidth=childNaturalWidth; minHeight=(numberChildren*childMinHeight); naturalHeight=(numberChildren*childNaturalHeight); } } /* Add spacing */ if(numberChildren>0) { numberChildren--; if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { minWidth+=numberChildren*priv->spacing; naturalWidth+=numberChildren*priv->spacing; } else { minHeight+=numberChildren*priv->spacing; naturalHeight+=numberChildren*priv->spacing; } } /* Depending on orientation set sizes to fit into parent actor */ parent=clutter_actor_get_parent(CLUTTER_ACTOR(inContainer)); if(parent) { aspectRatio=1.0f; clutter_actor_get_size(CLUTTER_ACTOR(parent), &parentWidth, &parentHeight); if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { if(priv->keepAspect==TRUE) { aspectRatio=minWidth/minHeight; minHeight=parentHeight; minWidth=minHeight*aspectRatio; aspectRatio=naturalWidth/naturalHeight; naturalHeight=parentHeight; naturalWidth=naturalHeight*aspectRatio; } else { minHeight=parentHeight; naturalHeight=parentHeight; } } else { if(priv->keepAspect==TRUE) { aspectRatio=minHeight/minWidth; minWidth=parentWidth; minHeight=minWidth*aspectRatio; aspectRatio=naturalHeight/naturalWidth; naturalWidth=parentWidth; naturalHeight=naturalWidth*aspectRatio; } else { minWidth=parentWidth; naturalWidth=parentWidth; } } } /* Set return values */ if(outMinWidth) *outMinWidth=minWidth; if(outNaturalWidth) *outNaturalWidth=naturalWidth; if(outMinHeight) *outMinHeight=minHeight; if(outNaturalHeight) *outNaturalHeight=naturalHeight; }
static void mnp_world_clock_construct (MnpWorldClock *world_clock) { ClutterActor *entry, *box, *stage; MxBoxLayout *table = (MxBoxLayout *)world_clock; gfloat width, height; MnpWorldClockPrivate *priv = GET_PRIVATE (world_clock); stage = priv->stage; priv->location_tile = FALSE; mx_box_layout_set_orientation ((MxBoxLayout *)world_clock, MX_ORIENTATION_VERTICAL); mx_box_layout_set_spacing ((MxBoxLayout *)world_clock, 0); clutter_actor_set_name (CLUTTER_ACTOR(world_clock), "TimePane"); construct_heading_and_top_area (world_clock); priv->completion_timeout = 0; /* Search Entry */ box = mx_box_layout_new (); mx_box_layout_set_enable_animations ((MxBoxLayout *)box, TRUE); mx_box_layout_set_orientation ((MxBoxLayout *)box, MX_ORIENTATION_HORIZONTAL); mx_box_layout_set_spacing ((MxBoxLayout *)box, 4); priv->entry_box = box; mx_stylable_set_style_class (MX_STYLABLE(box), "ZoneSearchEntryBox"); entry = mx_entry_new (); mx_stylable_set_style_class (MX_STYLABLE (entry), "ZoneSearchEntry"); priv->search_location = (MxEntry *)entry; mx_entry_set_hint_text (MX_ENTRY (entry), _("Enter a country or city")); mx_entry_set_secondary_icon_from_file (MX_ENTRY (entry), THEMEDIR"/edit-clear.png"); g_signal_connect (entry, "secondary-icon-clicked", G_CALLBACK (clear_btn_clicked_cb), world_clock); g_signal_connect (G_OBJECT (entry), "notify::text", G_CALLBACK (text_changed_cb), world_clock); clutter_actor_get_size (entry, &width, &height); clutter_actor_set_size (entry, width+10, -1); mx_box_layout_add_actor ((MxBoxLayout *)box, entry, 0); clutter_container_child_set (CLUTTER_CONTAINER (box), entry, "expand", FALSE, "y-fill", FALSE, "x-fill", FALSE, "y-align", MX_ALIGN_MIDDLE, "x-align", MX_ALIGN_START, NULL); priv->add_location = mx_button_new (); mx_button_set_label ((MxButton *)priv->add_location, _("Add")); mx_stylable_set_style_class (MX_STYLABLE(priv->add_location), "ZoneSearchEntryAddButton"); /* mx_box_layout_add_actor ((MxBoxLayout *)box, priv->add_location, 1); */ /* g_signal_connect (priv->add_location, "clicked", G_CALLBACK (add_location_clicked_cb), world_clock); */ /*clutter_container_child_set (CLUTTER_CONTAINER (box), priv->add_location, "expand", FALSE, "y-fill", FALSE, "y-align", MX_ALIGN_MIDDLE, NULL);*/ mx_box_layout_add_actor (MX_BOX_LAYOUT(priv->widget_box), box, -1); clutter_container_child_set (CLUTTER_CONTAINER (priv->widget_box), box, "expand", FALSE, "y-fill", FALSE, "x-fill", FALSE, "x-align", MX_ALIGN_START, NULL); /* Prep GeoClue */ priv->geo_position = geoclue_position_new ("org.freedesktop.Geoclue.Providers.Hostip", "/org/freedesktop/Geoclue/Providers/Hostip"); priv->geo_geocode = geoclue_geocode_new ("org.freedesktop.Geoclue.Providers.Yahoo", "/org/freedesktop/Geoclue/Providers/Yahoo"); priv->geo_reverse_geocode = geoclue_reverse_geocode_new ("org.freedesktop.Geoclue.Providers.Nominatim", "/org/freedesktop/Geoclue/Providers/Nominatim"); geoclue_position_get_position_async (priv->geo_position, mnp_wc_get_position_cb, world_clock); /* Clock Area */ priv->area = mnp_clock_area_new (); g_signal_connect (priv->area, "time-changed", G_CALLBACK(time_changed), world_clock); clutter_actor_set_size ((ClutterActor *)priv->area, 300, -1); clutter_actor_set_reactive ((ClutterActor *)priv->area, TRUE); clutter_actor_set_name ((ClutterActor *)priv->area, "WorldClockArea"); clutter_container_add_actor ((ClutterContainer *)stage, (ClutterActor *)priv->area); clutter_actor_lower_bottom ((ClutterActor *)priv->area); mx_droppable_enable ((MxDroppable *)priv->area); g_object_ref ((GObject *)priv->area); clutter_container_remove_actor ((ClutterContainer *)stage, (ClutterActor *)priv->area); mx_box_layout_add_actor ((MxBoxLayout *) table, (ClutterActor *)priv->area, -1); clutter_container_child_set (CLUTTER_CONTAINER (table), (ClutterActor *)priv->area, "expand", TRUE, "y-fill", TRUE, "x-fill", TRUE, NULL); priv->zones = mnp_load_zones (); mnp_clock_area_refresh_time (priv->area, TRUE); mnp_clock_area_set_zone_remove_cb (priv->area, (ZoneRemovedFunc) zone_removed_cb, (gpointer)world_clock); mnp_clock_area_set_zone_reordered_cb (priv->area, (ClockZoneReorderedFunc) zone_reordered_cb, (gpointer)world_clock); if (priv->zones->len) { int i=0; for (i=0; i<priv->zones->len; i++) { MnpZoneLocation *loc = (MnpZoneLocation *)priv->zones->pdata[i]; loc->local = FALSE; MnpClockTile *tile = mnp_clock_tile_new (loc, mnp_clock_area_get_time(priv->area), FALSE); mnp_clock_area_add_tile (priv->area, tile); } if (priv->zones->len >= 4) clutter_actor_hide (priv->entry_box); } /* div = clutter_texture_new_from_file (SINGLE_DIV_LINE, NULL); mx_box_layout_add_actor (MX_BOX_LAYOUT(world_clock), div, -1); */ box = mx_box_layout_new (); clutter_actor_set_name (box, "DateTimeLauncherBox"); priv->launcher_box = box; mx_box_layout_set_orientation ((MxBoxLayout *)box, MX_ORIENTATION_VERTICAL); mx_box_layout_set_spacing ((MxBoxLayout *)box, 6); priv->launcher = mx_button_new (); mx_button_set_label ((MxButton *) priv->launcher, _("Set Time & Date")); mx_stylable_set_style_class (MX_STYLABLE(priv->launcher), "DateTimeLauncherButton"); mx_box_layout_add_actor ((MxBoxLayout *)box, priv->launcher, -1); clutter_container_child_set (CLUTTER_CONTAINER (box), (ClutterActor *)priv->launcher, "expand", FALSE, "y-fill", FALSE, "x-fill", FALSE, "x-align", MX_ALIGN_END, NULL); mx_box_layout_add_actor ((MxBoxLayout *)world_clock, box, -1); }
static void pkg_graph_2d_paint (PkgGraph2d *graph) { PkgGraph2dPrivate *priv = graph->priv; cairo_t *cr; gfloat w, h; gdouble x0, x1, x2; gdouble y0, y1, y2; gdouble dashes[] = {1., 2.}; gdouble *epochs = NULL; gdouble tmp; gsize n_epochs = 0; gint i; clutter_cairo_texture_clear(CLUTTER_CAIRO_TEXTURE(priv->texture)); clutter_actor_get_size(CLUTTER_ACTOR(graph), &w, &h); /* * Create cairo context and set defaults. */ cr = clutter_cairo_texture_create(CLUTTER_CAIRO_TEXTURE(priv->texture)); cairo_set_line_width(cr, 1.); cairo_set_dash(cr, dashes, 2, 0.); /* * Get coordinates for drawing primary extends. */ pkg_graph_2d_get_primary_extents(graph, &x0, &x1, &x2, &y0, &y1, &y2); /* * Draw the background color. */ cairo_set_source_rgb(cr, 1., 1., 1.); cairo_rectangle(cr, x1, y2, x2 - x1, y1); cairo_fill(cr); /* * Draw the bounding box. */ cairo_set_source_rgb(cr, 0., 0., 0.); cairo_move_to(cr, x0, y2); cairo_line_to(cr, x2, y2); cairo_line_to(cr, x2, y0); cairo_move_to(cr, x0, y1); cairo_line_to(cr, x2, y1); cairo_move_to(cr, x1, y0 - .5); cairo_line_to(cr, x1, y2); cairo_stroke(cr); /* * Draw the x-scale epochs. */ if (pkg_scale_get_epochs(priv->x_scale, &epochs, &n_epochs)) { if (n_epochs > 0) { for (i = 0; i < n_epochs; i++) { if (pkg_scale_translate(priv->x_scale, epochs[i], &tmp)) { PangoFontDescription *font_desc; PangoLayout *layout; gchar *format, *markup; gint pw, ph; /* * Only draw the line if it isn't right near the end of * the visiable region of the graph. */ if (tmp + 5. < floor(w)) { cairo_move_to(cr, tmp, y0 - .5); cairo_line_to(cr, tmp, y2); } /* * Draw the y-scale grid-line value. */ format = pkg_scale_format_string(priv->x_scale, epochs[i]); if (format != NULL) { font_desc = pango_font_description_from_string("Bold Sans 8"); layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, font_desc); markup = g_strdup_printf("<span size=\"smaller\">%s</span>", format); pango_layout_set_markup(layout, markup, -1); pango_layout_get_pixel_size(layout, &pw, &ph); if (i == 0) { cairo_move_to(cr, tmp + 2., y1 + 2.); } else { cairo_move_to(cr, tmp - pw - 2., y1 + 2.); } pango_cairo_show_layout(cr, layout); g_object_unref(layout); pango_font_description_free(font_desc); g_free(format); g_free(markup); } } } cairo_stroke(cr); } } /* * Draw the y-scale epochs. */ if (pkg_scale_get_epochs(priv->y_scale, &epochs, &n_epochs)) { if (n_epochs > 0) { for (i = 0; i < n_epochs; i++) { if (pkg_scale_translate(priv->y_scale, epochs[i], &tmp)) { PangoFontDescription *font_desc; PangoLayout *layout; gchar *format, *markup; gint pw, ph; cairo_move_to(cr, x0, floor(y1 - tmp) + .5); cairo_line_to(cr, x2, floor(y1 - tmp) + .5); /* * Draw the y-scale grid-line value. */ format = pkg_scale_format_string(priv->y_scale, epochs[i]); if (format != NULL) { font_desc = pango_font_description_from_string("Bold Sans 8"); layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, font_desc); markup = g_strdup_printf("<span size=\"smaller\">%s</span>", format); pango_layout_set_markup(layout, markup, -1); pango_layout_get_pixel_size(layout, &pw, &ph); if (i == 0) { cairo_move_to(cr, x1 - pw - 2., y1 - tmp - ph - 2.); } else { cairo_move_to(cr, x1 - pw - 2., y1 - tmp + 2.); } pango_cairo_show_layout(cr, layout); g_object_unref(layout); pango_font_description_free(font_desc); g_free(markup); g_free(format); } } } cairo_stroke(cr); } } priv->x_label = "X Label Here"; priv->y_label = "Y Label Here"; /* * Draw the X scale label. */ if (priv->x_label) { PangoFontDescription *font_desc; PangoLayout *layout; gchar *markup; gint pw, ph; font_desc = pango_font_description_from_string("Bold Sans 10"); layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, font_desc); markup = g_strdup_printf("<span size=\"smaller\">%s</span>", priv->x_label); pango_layout_set_markup(layout, markup, -1); pango_layout_get_pixel_size(layout, &pw, &ph); cairo_move_to(cr, ((w - pw) / 2.), h - ph); pango_cairo_show_layout(cr, layout); g_object_unref(layout); pango_font_description_free(font_desc); g_free(markup); } /* * Draw the Y scale label. */ if (priv->x_label) { PangoFontDescription *font_desc; PangoLayout *layout; gchar *markup; gint pw, ph; font_desc = pango_font_description_from_string("Bold Sans 10"); layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, font_desc); markup = g_strdup_printf("<span size=\"smaller\">%s</span>", priv->y_label); pango_layout_set_markup(layout, markup, -1); pango_layout_get_pixel_size(layout, &pw, &ph); cairo_move_to(cr, 0., h - ((h - pw) / 2.)); cairo_rotate(cr, M_PI / -2.); pango_cairo_show_layout(cr, layout); g_object_unref(layout); pango_font_description_free(font_desc); g_free(markup); } /* * Free cairo context and resources. */ cairo_destroy(cr); /* * Render the children data points. */ pkg_graph_2d_paint_children(graph); }
static gboolean st_background_effect_pre_paint (ClutterEffect *effect) { StBackgroundEffect *self = ST_BACKGROUND_EFFECT (effect); ClutterEffectClass *parent_class; gfloat width; gfloat height; gfloat posx; gfloat posy; guchar *data; guint size; guint rowstride; glong new_time; gdouble time_used; ClutterActor *stage; gfloat stage_width; gfloat stage_height; if (self->bg_bumpmap == NULL) return FALSE; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); if (self->actor == NULL) return FALSE; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShaderEffect: the graphics hardware " "or the current GL driver does not implement support " "for the GLSL shading language."); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); return FALSE; } new_time = clock(); time_used = ((double) (new_time - self->old_time)*100) / (double) CLOCKS_PER_SEC; self->old_time = new_time; posx = 0.0f; posy = 0.0f; width = 0.0f; height = 0.0f; stage_width = 0.0f; stage_height = 0.0f; clutter_actor_get_transformed_position (self->actor, &posx, &posy); clutter_actor_get_transformed_size (self->actor, &width, &height); self->opacity = clutter_actor_get_paint_opacity (self->actor); stage = clutter_actor_get_stage (self->actor); clutter_actor_get_size (stage, &stage_width, &stage_height); if ((posx < 0) || (posy < 0) || ((posx + width) > stage_width) || ((posy + height) > stage_height)) return FALSE; if (( posx != self->posx_old) || ( posy != self->posy_old) || ( width != self->width_old) || ( height != self->height_old) || (time_used > 50.0)) { self->posx_old = posx; self->posy_old = posy; self->width_old = width; self->height_old = height; self->bg_posx_i = round(posx)+2; self->bg_posy_i = round(posy)+2; self->bg_width_i = round(width)-4; self->bg_height_i = round(height)-4; size = (self->bg_width_i) * (self->bg_height_i) * 4; if (((self->opacity == 0xff) || (self->bg_texture == NULL)) && (size > 400)) { rowstride = (self->bg_width_i) * 4; data = g_malloc (size); cogl_read_pixels (self->bg_posx_i, self->bg_posy_i, self->bg_width_i, self->bg_height_i, COGL_READ_PIXELS_COLOR_BUFFER, COGL_PIXEL_FORMAT_RGBA_8888_PRE, data); if (data != NULL) { if (self->bg_texture != NULL) { cogl_handle_unref (self->bg_texture); self->bg_texture = NULL; } self->bg_texture = cogl_texture_new_from_data (self->bg_width_i, self->bg_height_i, COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_PIXEL_FORMAT_RGBA_8888_PRE, rowstride, data); g_free (data); } } } parent_class = CLUTTER_EFFECT_CLASS (st_background_effect_parent_class); if (parent_class->pre_paint (effect)) { ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect); CoglHandle fg_texture; fg_texture = clutter_offscreen_effect_get_texture (offscreen_effect); if (fg_texture != COGL_INVALID_HANDLE) { self->fg_width_i = cogl_texture_get_width (fg_texture); self->fg_height_i = cogl_texture_get_height (fg_texture); if ((self->bg_texture != NULL) && (self->opacity == 0xff)) { if (self->pixel_step_uniform0 > -1) { gfloat pixel_step[3]; pixel_step[0] = 1.0f / (self->bg_width_i); pixel_step[1] = 1.0f / (self->bg_height_i); pixel_step[2] = 0.0f; cogl_pipeline_set_uniform_float (self->pipeline0, self->pixel_step_uniform0, 3, 1, pixel_step); } if (self->BumpTex_uniform > -1) { cogl_pipeline_set_uniform_1i (self->pipeline0, self->BumpTex_uniform, 1); } if (self->bump_step_uniform > -1) { gfloat bump_step[2]; bump_step[0] = 1.0f / (self->bumptex_width_i); bump_step[1] = 1.0f / (self->bumptex_height_i); cogl_pipeline_set_uniform_float (self->pipeline0, self->bump_step_uniform, 2, 1, bump_step); } if (self->bg_sub_texture != NULL) { cogl_handle_unref (self->bg_sub_texture); self->bg_sub_texture = NULL; } self->bg_sub_texture = cogl_texture_new_with_size (self->bg_width_i, self->bg_height_i, COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_RGBA_8888_PRE); cogl_pipeline_set_layer_texture (self->pipeline0, 0, self->bg_texture); if (self->pixel_step_uniform1 > -1) { gfloat pixel_step[3]; pixel_step[0] = 1.0f / (self->bg_width_i); pixel_step[1] = 1.0f / (self->bg_height_i); pixel_step[2] = 1.0f; cogl_pipeline_set_uniform_float (self->pipeline1, self->pixel_step_uniform1, 3, 1, pixel_step); } if (self->pixel_step_uniform2 > -1) { gfloat pixel_step[3]; pixel_step[0] = 1.0f / (self->fg_width_i); pixel_step[1] = 1.0f / (self->fg_height_i); pixel_step[2] = 2.0f; cogl_pipeline_set_uniform_float (self->pipeline3, self->pixel_step_uniform2, 3, 1, pixel_step); } } cogl_pipeline_set_layer_texture (self->pipeline2, 0, fg_texture); cogl_pipeline_set_layer_texture (self->pipeline3, 0, fg_texture); cogl_pipeline_set_layer_texture (self->pipeline4, 0, fg_texture); } return TRUE; } else { return FALSE; } }
/* Re-layout and allocate children of container we manage */ static void _xfdashboard_scaled_table_layout_allocate(ClutterLayoutManager *self, ClutterContainer *inContainer, const ClutterActorBox *inAllocation, ClutterAllocationFlags inFlags) { XfdashboardScaledTableLayoutPrivate *priv; gint row, col; ClutterActor *child; ClutterActorIter iter; gfloat cellWidth, cellHeight; gfloat childWidth, childHeight; gfloat scaledChildWidth, scaledChildHeight; gfloat largestWidth, largestHeight; gfloat scaleWidth, scaleHeight; gfloat aspectRatio; gfloat x, y; ClutterActorBox childAllocation; g_return_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self)); g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer)); priv=XFDASHBOARD_SCALED_TABLE_LAYOUT(self)->priv; /* Get size of container holding children to layout and * determine size of a cell */ clutter_actor_get_size(CLUTTER_ACTOR(inContainer), &childWidth, &childHeight); cellWidth=childWidth-((priv->columns-1)*priv->columnSpacing); cellWidth=floor(cellWidth/priv->columns); cellHeight=childHeight-((priv->rows-1)*priv->rowSpacing); cellHeight=floor(cellHeight/priv->rows); /* Iterate through children and find largest one * if relative scale was set */ largestWidth=largestHeight=0.0f; if(priv->relativeScale==TRUE) { gfloat w, h; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { if(!clutter_actor_is_visible(child)) continue; clutter_actor_get_preferred_size(child, NULL, NULL, &w, &h); if(w>largestWidth) largestWidth=w; if(h>largestHeight) largestHeight=h; } } /* Iterate through child actors and set their new allocation */ row=col=0; x=y=0.0f; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { if(!clutter_actor_is_visible(child)) continue; /* Get natural size of actor */ clutter_actor_get_preferred_size(child, NULL, NULL, &childWidth, &childHeight); /* If either width or height is 0 then it is visually hidden and we * skip expensive calculation. This also has the nice effect that * do not perform invalid divisions by zero ;) */ if(childWidth>0.0f && childHeight>0.0f) { /* Get scale factor needed to apply to width and height. * If no relative scaling should be performed the scale is always 1.0 * otherwise it is the scale factor for this actor to the largest one. */ if(priv->relativeScale==TRUE) { /* Get scale factors */ scaleWidth=childWidth/largestWidth; scaleHeight=childHeight/largestHeight; } else scaleWidth=scaleHeight=1.0f; /* Get aspect ratio factor */ aspectRatio=childHeight/childWidth; /* Calculate new size of child */ scaledChildWidth=cellWidth*scaleWidth; scaledChildHeight=scaledChildWidth*aspectRatio; if(scaledChildHeight>cellHeight) { scaledChildHeight=cellHeight*scaleHeight; scaledChildWidth=scaledChildHeight/aspectRatio; } /* If upscaling should be prevent check if we are upscaling now */ if(priv->preventUpscaling) { if(scaledChildWidth>childWidth) { scaledChildWidth=childWidth; scaledChildHeight=childWidth*aspectRatio; } if(scaledChildHeight>childHeight) { scaledChildHeight=childHeight; scaledChildWidth=childHeight/aspectRatio; } } } else { /* Visually hidden so do not allocate any space */ scaledChildWidth=0.0f; scaledChildHeight=0.0f; } /* Set new allocation of child */ childAllocation.x1=ceil(x+((cellWidth-scaledChildWidth)/2.0f)); childAllocation.y1=ceil(y+((cellHeight-scaledChildHeight)/2.0f)); childAllocation.x2=ceil(childAllocation.x1+scaledChildWidth); childAllocation.y2=ceil(childAllocation.y1+scaledChildHeight); clutter_actor_allocate(child, &childAllocation, inFlags); /* Set up for next child */ col=(col+1) % priv->columns; if(col==0) row++; x=col*(cellWidth+priv->columnSpacing); y=row*(cellHeight+priv->rowSpacing); } }
void _clutter_backend_ensure_context (ClutterBackend *backend, ClutterStage *stage) { static ClutterStage *current_context_stage = NULL; g_assert (CLUTTER_IS_BACKEND (backend)); g_assert (CLUTTER_IS_STAGE (stage)); if (current_context_stage != stage || !clutter_actor_is_realized (CLUTTER_ACTOR (stage))) { ClutterStage *new_stage = NULL; if (!clutter_actor_is_realized (CLUTTER_ACTOR (stage))) { new_stage = NULL; CLUTTER_NOTE (BACKEND, "Stage [%p] is not realized, unsetting the stage", stage); } else { new_stage = stage; CLUTTER_NOTE (BACKEND, "Setting the new stage [%p]", new_stage); } /* XXX: Until Cogl becomes fully responsible for backend windows * Clutter need to manually keep it informed of the current window size * * NB: This must be done after we ensure_context above because Cogl * always assumes there is a current GL context. */ if (new_stage != NULL) { float width, height; _clutter_backend_ensure_context_internal (backend, new_stage); clutter_actor_get_size (CLUTTER_ACTOR (stage), &width, &height); cogl_onscreen_clutter_backend_set_size (width, height); /* Eventually we will have a separate CoglFramebuffer for * each stage and each one will track private projection * matrix and viewport state, but until then we need to make * sure we update the projection and viewport whenever we * switch between stages. * * This dirty mechanism will ensure they are asserted before * the next paint... */ _clutter_stage_dirty_viewport (stage); _clutter_stage_dirty_projection (stage); } /* FIXME: With a NULL stage and thus no active context it may make more * sense to clean the context but then re call with the default stage * so at least there is some kind of context in place (as to avoid * potential issue of GL calls with no context). */ current_context_stage = new_stage; } else CLUTTER_NOTE (BACKEND, "Stage is the same"); }
static void clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect) { ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect); ClutterDeformEffectPrivate *priv = self->priv; gboolean is_depth_enabled, is_cull_enabled; CoglHandle material; gint n_tiles; if (priv->is_dirty) { ClutterActor *actor; gfloat width, height; guint opacity; gint i, j; actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); opacity = clutter_actor_get_paint_opacity (actor); /* if we don't have a target size, fall back to the actor's * allocation, though wrong it might be */ if (!clutter_offscreen_effect_get_target_size (effect, &width, &height)) clutter_actor_get_size (actor, &width, &height); for (i = 0; i < priv->y_tiles + 1; i++) { for (j = 0; j < priv->x_tiles + 1; j++) { CoglTextureVertex *vertex; vertex = &priv->vertices[(i * (priv->x_tiles + 1)) + j]; vertex->tx = (float) j / priv->x_tiles; vertex->ty = (float) i / priv->y_tiles; vertex->x = width * vertex->tx; vertex->y = height * vertex->ty; vertex->z = 0.0f; cogl_color_init_from_4ub (&vertex->color, 255, 255, 255, opacity); _clutter_deform_effect_deform_vertex (self, width, height, vertex); } } /* XXX in theory, the sub-classes should tell us what they changed * in the texture vertices; we then would be able to avoid resubmitting * the same data, if it did not change. for the time being, we resubmit * everything */ cogl_vertex_buffer_add (priv->vbo, "gl_Vertex", 3, COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, sizeof (CoglTextureVertex), &priv->vertices->x); cogl_vertex_buffer_add (priv->vbo, "gl_MultiTexCoord0", 2, COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, sizeof (CoglTextureVertex), &priv->vertices->tx); cogl_vertex_buffer_add (priv->vbo, "gl_Color", 4, COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE, FALSE, sizeof (CoglTextureVertex), &priv->vertices->color); priv->is_dirty = FALSE; } /* enable depth test, if it's not already enabled */ is_depth_enabled = cogl_get_depth_test_enabled (); if (!is_depth_enabled) cogl_set_depth_test_enabled (TRUE); /* enable backface culling if it's not already enabled and if * we have a back material */ is_cull_enabled = cogl_get_backface_culling_enabled (); if (priv->back_material != COGL_INVALID_HANDLE && !is_cull_enabled) cogl_set_backface_culling_enabled (TRUE); else if (priv->back_material == COGL_INVALID_HANDLE && is_cull_enabled) cogl_set_backface_culling_enabled (FALSE); n_tiles = (priv->x_tiles + 1) * (priv->y_tiles + 1); /* draw the front */ material = clutter_offscreen_effect_get_target (effect); if (material != COGL_INVALID_HANDLE) { cogl_set_source (material); cogl_vertex_buffer_draw_elements (priv->vbo, COGL_VERTICES_MODE_TRIANGLE_STRIP, priv->indices, 0, n_tiles, 0, priv->n_indices); } /* draw the back */ material = priv->back_material; if (material != COGL_INVALID_HANDLE) { cogl_set_source (priv->back_material); cogl_vertex_buffer_draw_elements (priv->vbo, COGL_VERTICES_MODE_TRIANGLE_STRIP, priv->back_indices, 0, n_tiles, 0, priv->n_indices); } /* restore the previous state */ if (!is_depth_enabled) cogl_set_depth_test_enabled (FALSE); if (priv->back_material != COGL_INVALID_HANDLE && !is_cull_enabled) cogl_set_backface_culling_enabled (FALSE); else if (priv->back_material == COGL_INVALID_HANDLE && is_cull_enabled) cogl_set_backface_culling_enabled (TRUE); }
static void on_clicked (ClutterClickAction *action, ClutterActor *actor, gpointer dummy G_GNUC_UNUSED) { ClutterAnimation *animation; gfloat old_x, old_y, new_x, new_y; gfloat old_width, old_height, new_width, new_height; gdouble new_angle; ClutterVertex vertex = { 0, }; ClutterColor new_color = { 0, }; clutter_actor_get_position (actor, &old_x, &old_y); clutter_actor_get_size (actor, &old_width, &old_height); /* determine the final state of the animation depending on * the state of the actor */ if (!is_expanded) { new_x = old_x - 100; new_y = old_y - 100; new_width = old_width + 200; new_height = old_height + 200; new_angle = 360.0; new_color.red = 0xdd; new_color.green = 0x44; new_color.blue = 0xdd; new_color.alpha = 0xff; } else { new_x = old_x + 100; new_y = old_y + 100; new_width = old_width - 200; new_height = old_height - 200; new_angle = 0.0; new_color.red = 0x44; new_color.green = 0xdd; new_color.blue = 0x44; new_color.alpha = 0x88; } vertex.x = new_width / 2; vertex.y = new_height / 2; vertex.z = 0.0; animation = clutter_actor_animate (actor, CLUTTER_EASE_IN_EXPO, 2000, "x", new_x, "y", new_y, "width", new_width, "height", new_height, "color", &new_color, "rotation-angle-z", new_angle, "fixed::rotation-center-z", &vertex, "fixed::reactive", FALSE, NULL); g_signal_connect (animation, "completed", G_CALLBACK (on_animation_complete), actor); }
static void mx_combo_box_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { MxComboBoxPrivate *priv = MX_COMBO_BOX (actor)->priv; MxPadding padding; gfloat x, y, width, height; gfloat min_menu_h, nat_menu_h; gfloat label_h; gfloat nat_icon_h, icon_h, icon_w; gfloat nat_marker_h, marker_h, marker_w; ClutterActorBox childbox; ClutterActor *menu, *stage; CLUTTER_ACTOR_CLASS (mx_combo_box_parent_class)->allocate (actor, box, flags); mx_widget_get_padding (MX_WIDGET (actor), &padding); x = padding.left; y = padding.top; width = box->x2 - box->x1 - padding.left - padding.right; height = box->y2 - box->y1 - padding.top - padding.bottom; icon_w = marker_w = 0; if (priv->icon) { /* Allocate the icon, if there is one, the space not used by the text */ clutter_actor_get_preferred_height (priv->icon, -1, NULL, &nat_icon_h); if (height >= nat_icon_h) { icon_h = nat_icon_h; clutter_actor_get_preferred_width (priv->icon, -1, NULL, &icon_w); } else { icon_h = height; clutter_actor_get_preferred_width (priv->icon, icon_h, NULL, &icon_w); } childbox.x1 = (int)(x); childbox.y1 = (int)(y + (height - icon_h) / 2); childbox.x2 = (int)(x + icon_w); childbox.y2 = (int)(childbox.y1 + icon_h); clutter_actor_allocate (priv->icon, &childbox, flags); icon_w += priv->spacing; } if (priv->marker) { clutter_actor_get_preferred_height (priv->marker, -1, NULL, &nat_marker_h); if (height >= nat_marker_h) { marker_h = nat_marker_h; clutter_actor_get_preferred_width (priv->marker, -1, NULL, &marker_w); } else { marker_h = height; clutter_actor_get_preferred_width (priv->marker, marker_h, NULL, &marker_w); } childbox.x2 = (int)(x + width); childbox.x1 = (int)(childbox.x2 - marker_w); childbox.y1 = (int)(y + (height - marker_h) / 2); childbox.y2 = (int)(childbox.y1 + marker_h); clutter_actor_allocate (priv->marker, &childbox, flags); marker_w += priv->spacing; } clutter_actor_get_preferred_height (priv->label, -1, NULL, &label_h); childbox.x1 = (int)(x + icon_w); childbox.y1 = (int)(y + (height / 2 - label_h / 2)); childbox.x2 = (int)(x + width - marker_w); childbox.y2 = (int)(childbox.y1 + label_h); clutter_actor_allocate (priv->label, &childbox, flags); menu = (ClutterActor*) mx_widget_get_menu (MX_WIDGET (actor)); clutter_actor_get_preferred_height (menu, (box->x2 - box->x1), &min_menu_h, &nat_menu_h); childbox.x1 = 0; childbox.x2 = (box->x2 - box->x1); childbox.y1 = (box->y2 - box->y1); stage = clutter_actor_get_stage (actor); if (stage != NULL) { ClutterVertex point = { 0, }; gfloat stage_w, stage_h, combo_h = box->y2 - box->y1; clutter_actor_get_size (stage, &stage_w, &stage_h); point.y = combo_h + nat_menu_h; clutter_actor_apply_transform_to_point (actor, &point, &point); /* If the menu would appear off the stage, flip it around. */ if ((point.x < 0) || (point.x >= stage_w) || (point.y < 0) || (point.y >= stage_h)) { childbox.y1 = -nat_menu_h; } } childbox.y2 = childbox.y1 + nat_menu_h; clutter_actor_allocate (menu, &childbox, flags); }
static void mx_tooltip_update_position (MxTooltip *tooltip) { MxTooltipPrivate *priv = tooltip->priv; ClutterGeometry tip_area = *tooltip->priv->tip_area; gfloat tooltip_w, tooltip_h, tooltip_x, tooltip_y, abs_x, abs_y; ClutterActor *stage, *parent; gfloat stage_w, stage_h, parent_w, parent_h; MxWindow *window; /* If there's no stage, bail out - there's nothing we can do */ stage = clutter_actor_get_stage ((ClutterActor *) tooltip); if (!stage) return; /* find out the stage's size to keep the tooltip on-screen */ clutter_actor_get_size (stage, &stage_w, &stage_h); parent = clutter_actor_get_parent ((ClutterActor *) tooltip); clutter_actor_get_transformed_position (parent, &abs_x, &abs_y); clutter_actor_get_size (parent, &parent_w, &parent_h); /* ensure the tooltip with is not fixed size */ clutter_actor_set_size ((ClutterActor*) tooltip, -1, -1); /* if no area set, just position ourselves top left */ if (!priv->tip_area) { clutter_actor_set_position ((ClutterActor*) tooltip, abs_x, abs_y); return; } /* check if we're in a window and if there's rotation */ window = mx_window_get_for_stage (CLUTTER_STAGE (stage)); if (window) { MxWindowRotation rotation; gfloat old_x; g_object_get (G_OBJECT (window), "window-rotation", &rotation, NULL); if (rotation == MX_WINDOW_ROTATION_90 || rotation == MX_WINDOW_ROTATION_270) { /* swap stage width and height */ old_x = stage_w; stage_w = stage_h; stage_h = old_x; /* swap tip area width and height */ old_x = tip_area.width; tip_area.width = tip_area.height; tip_area.height = old_x; } switch (rotation) { case MX_WINDOW_ROTATION_90: /* absolute position */ old_x = abs_x; abs_x = abs_y; abs_y = stage_h - old_x; /* tip area */ old_x = tip_area.x; tip_area.x = tip_area.y; tip_area.y = stage_h - old_x - tip_area.height; break; case MX_WINDOW_ROTATION_180: tip_area.x = stage_w - tip_area.x - tip_area.width; tip_area.y = stage_h - tip_area.y - tip_area.height; abs_x = stage_w - abs_x; abs_y = stage_h - abs_y; break; case MX_WINDOW_ROTATION_270: /* absolute position */ old_x = abs_x; abs_x = stage_w - abs_y; abs_y = old_x; /* tip area */ old_x = tip_area.x; tip_area.x = stage_w - tip_area.y - tip_area.width; tip_area.y = old_x; break; default: break; } } /* we need to have a style in case there are padding values to take into * account when calculating width/height */ mx_stylable_style_changed (MX_STYLABLE (tooltip), MX_STYLE_CHANGED_FORCE); /* find out the tooltip's size */ clutter_actor_get_size ((ClutterActor*) tooltip, &tooltip_w, &tooltip_h); /* attempt to place the tooltip */ /* This special-cases the 4 window rotations, as doing this with * arbitrary rotations would massively complicate the code for * little benefit. */ priv->actor_below = FALSE; tooltip_x = (int)(tip_area.x + (tip_area.width / 2) - (tooltip_w / 2)); tooltip_y = (int)(tip_area.y + tip_area.height); /* Keep on the screen vertically */ if (tooltip_y + tooltip_h > stage_h) { priv->actor_below = TRUE; /* re-query size as may have changed */ clutter_actor_get_preferred_height ((ClutterActor*) tooltip, -1, NULL, &tooltip_h); tooltip_y = MAX (0, tip_area.y - tooltip_h); } /* Keep on the screen horizontally */ if (tooltip_w > stage_w) { tooltip_x = 0; clutter_actor_set_width ((ClutterActor*) tooltip, stage_w); } else if (tooltip_x < 0) tooltip_x = 0; else if (tooltip_x + tooltip_w > stage_w) tooltip_x = (int)(stage_w) - tooltip_w; gfloat pos_x, pos_y; pos_x = tooltip_x - abs_x; pos_y = tooltip_y - abs_y; /* calculate the arrow offset */ priv->arrow_offset = tip_area.x + tip_area.width / 2 - tooltip_x; clutter_actor_set_position ((ClutterActor*) tooltip, pos_x, pos_y); }