#include #include #include #include #include #include "gdancer.h" #include "config.h" #include "gui.h" #include "about.h" #include "image.h" #include "audioprocessing.h" #include "../pics/gdancer_mini.xpm" // These defines are for the sticky hint #define WIN_STATE_STICKY (1<<0) /* sticky window hint */ #define XA_WIN_STATE "_WIN_STATE" /* ? */ Atom _XA_WIN_STATE; static GdkPixmap *gdancer_icon = NULL; static GdkBitmap *gdancer_icon_mask = NULL; void gd_move_window (GDancer *dancer) { if (!dancer->window) return; // Make sure theres a window to move #if DEBUGGING printf ("Moving window to %d , %d\n", dancer->x, dancer->y); #endif gdk_window_move (dancer->window->window, dancer->x, dancer->y); } void dancer_raise (GtkWidget *widget, GDancer *dancer) { gdk_window_raise (dancer->window->window); } void dancer_lower (GtkWidget *widget, GDancer *dancer) { gdk_window_lower (dancer->window->window); } // Function for moving dancer void move_dancer (GDancer *dancer, gint x, gint y) { if (dancer->window == NULL) return; // Make sure thre is a window gdk_window_move (dancer->window->window, x, y); } // Signal callback for when someone presses their mouse button on the dancer void dancer_press (GtkWidget *widget, GdkEventButton *event, GDancer *dancer) { if (event->button == 1) { // Store the coordinates of where they pressed on the dancer dancer->press_x = event->x; dancer->press_y = event->y; // tells gdancer since they pressed down on the mouse // its ok to move the character. dancer->move_window = TRUE; } else if (event->button == 3) { // Show popup menu gtk_menu_popup(GTK_MENU(dancer->menu.mainmenu), NULL, NULL, NULL, NULL, event->button, event->time); } } // Signal callback for when someone releases button on dancer void dancer_release (GtkWidget *widget, GdkEventButton *event, GDancer *dancer) { gint release_x, release_y; gint pointer_x, pointer_y; // Get the X and Y points of the mouse release, relative to the app release_x = event->x; release_y = event->y; // Get the pointer coordinates relative to the whole screen gdk_window_get_pointer(NULL, &pointer_x, &pointer_y, NULL); // Figure out the coordinates of the window dancer->x = pointer_x - release_x; dancer->y = pointer_y - release_y; dancer->move_window = FALSE; } // Signal callback for when someone drags the dancer with their mouse void dancer_motion (GtkWidget *widget, GdkEventMotion *event, GDancer *dancer) { gint motion_x, motion_y; // Make sure they're holding down the mouse button if (dancer->move_window != TRUE) return; // Get coordinates of mouse gdk_window_get_pointer(NULL, &motion_x, &motion_y, NULL); // Since it moves the window by the coordinates of the upper left // corner, we have to determine where that is by subtracting where // they pressed it then move the window move_dancer (dancer, motion_x - dancer->press_x, motion_y - dancer->press_y); } gint clean_dancer (GDancer *dancer, gpointer data) { if (dancer->window) { gtk_signal_disconnect_by_func (GTK_OBJECT(dancer->window), GTK_SIGNAL_FUNC(destroy_dancer), dancer); clear_images(dancer); if (dancer->menu.mainmenu) { gtk_widget_destroy (dancer->menu.exit); gtk_widget_destroy (dancer->menu.add); gtk_widget_destroy (dancer->menu.delete); gtk_widget_destroy (dancer->menu.lower); gtk_widget_destroy (dancer->menu.raise); gtk_widget_destroy (dancer->menu.about); gtk_widget_destroy (dancer->menu.config); gtk_widget_destroy (dancer->menu.gblconfig); gtk_widget_destroy (dancer->menu.mainmenu); } if (dancer->pixmap) gtk_widget_destroy (dancer->pixmap); if (dancer->event_box) gtk_widget_destroy (dancer->event_box); if (dancer->window) gtk_widget_destroy (dancer->window); g_free(dancer->style->klass); g_free(dancer->style); g_free(dancer); } } void destroy_dancer (GtkWidget *widget, GDancer *dancer) { if (g_list_length(gdancers) == 1) { // Only one dancer left, so instead of deleting // dancer, just disable plugin gdancer_vp.disable_plugin(&gdancer_vp); return; } gdancers = g_list_remove (gdancers, dancer); clean_dancer (dancer, NULL); } // Disable the whole plugin (all dancers) void disable_gdancer (GtkWidget *widget, gpointer data) { gdancer_vp.disable_plugin(&gdancer_vp); } void gdancer_set_icon (GDancer *dancer) { // Set the icon for the dancer's window if (gdancer_icon == NULL) gdancer_icon = gdk_pixmap_create_from_xpm_d( dancer->window->window, &gdancer_icon_mask, NULL, gdancer_mini_xpm); gdk_window_set_icon (dancer->window->window, NULL, gdancer_icon, gdancer_icon_mask); } // We don't want anyone to use this refresh call. But we // provide a dummy version so GTK does not complain. void dummy_draw_flat_box (GtkStyle *style, GdkWindow *window, GtkStateType state_type, GtkShadowType shadow_type, GdkRectangle *area, GtkWidget *widget, gchar *detail, gint x, gint y, gint width, gint height) { } GDancer *gd_get_new_dancer_with_theme (gchar *theme) { // Make new dancer using GDancer structure GDancer *dancer; // Set memory for dancer dancer = g_malloc0 (sizeof(GDancer)); // We create a new style using dummy_draw_flat_box // This way, only "moving" regions are refreshed. dancer->style = gtk_style_new(); dancer->style->klass = g_malloc0 (sizeof(GtkStyleClass)); dancer->style->klass->draw_flat_box = dummy_draw_flat_box; // Add a pointer to this dancer in the dancers GList // so we can find it later gdancers = g_list_prepend(gdancers, dancer); // set the theme by the theme argument that was passed to us strcpy (dancer->theme, theme); // set hadlast to 0 (neutral) dancer->hadlast = 0; // Make window and set delete signal dancer->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_set_app_paintable(dancer->window, TRUE); gtk_window_set_title(GTK_WINDOW(dancer->window), PROGNAME); gtk_window_set_policy(GTK_WINDOW(dancer->window),FALSE,FALSE,TRUE); gtk_window_set_wmclass(GTK_WINDOW(dancer->window), "GDancer", "dancer"); gtk_widget_realize(dancer->window); gdancer_set_icon(dancer); gdk_window_set_decorations(dancer->window->window, 0); gtk_signal_connect (GTK_OBJECT(dancer->window), "destroy", GTK_SIGNAL_FUNC(destroy_dancer), dancer); // Make event box to catch button clicks and stuff dancer->event_box = gtk_event_box_new(); // Connect signals for moving and pressing on dancer gtk_signal_connect(GTK_OBJECT(dancer->event_box), "button_press_event", GTK_SIGNAL_FUNC(dancer_press), dancer); gtk_signal_connect(GTK_OBJECT(dancer->event_box), "button_release_event", GTK_SIGNAL_FUNC(dancer_release), dancer); gtk_signal_connect(GTK_OBJECT(dancer->event_box), "motion_notify_event", GTK_SIGNAL_FUNC(dancer_motion), dancer); // Make menu for dancer dancer->menu.mainmenu = gtk_menu_new(); dancer->menu.gblconfig = gtk_menu_item_new_with_label ("Global Config"); dancer->menu.config = gtk_menu_item_new_with_label ("Dancer Config (theme)"); dancer->menu.about = gtk_menu_item_new_with_label ("About GDancer"); dancer->menu.raise = gtk_menu_item_new_with_label ("Raise Dancer"); dancer->menu.lower = gtk_menu_item_new_with_label ("Lower Dancer"); dancer->menu.delete = gtk_menu_item_new_with_label ("Delete Dancer"); dancer->menu.add = gtk_menu_item_new_with_label ("New Dancer"); dancer->menu.exit = gtk_menu_item_new_with_label ("Disable Plugin"); // Add menu items to menu gtk_menu_append (GTK_MENU(dancer->menu.mainmenu), dancer->menu.gblconfig); gtk_menu_append (GTK_MENU(dancer->menu.mainmenu), dancer->menu.config); gtk_menu_append (GTK_MENU(dancer->menu.mainmenu),dancer->menu.raise); gtk_menu_append (GTK_MENU(dancer->menu.mainmenu), dancer->menu.lower); gtk_menu_append (GTK_MENU(dancer->menu.mainmenu), dancer->menu.add); gtk_menu_append (GTK_MENU(dancer->menu.mainmenu), dancer->menu.delete); gtk_menu_append (GTK_MENU(dancer->menu.mainmenu), dancer->menu.about); gtk_menu_append (GTK_MENU(dancer->menu.mainmenu), dancer->menu.exit); // Set signals for menu items gtk_signal_connect (GTK_OBJECT (dancer->menu.gblconfig), "activate", GTK_SIGNAL_FUNC (global_config), dancer); gtk_signal_connect(GTK_OBJECT (dancer->menu.about), "activate", GTK_SIGNAL_FUNC (show_about), dancer); gtk_signal_connect(GTK_OBJECT (dancer->menu.config), "activate", GTK_SIGNAL_FUNC (config_dancer), dancer); gtk_signal_connect(GTK_OBJECT (dancer->menu.raise), "activate", GTK_SIGNAL_FUNC (dancer_raise), dancer); gtk_signal_connect(GTK_OBJECT (dancer->menu.lower), "activate", GTK_SIGNAL_FUNC (dancer_lower), dancer); gtk_signal_connect (GTK_OBJECT (dancer->menu.add), "activate", GTK_SIGNAL_FUNC (gd_get_new_dancer), NULL); gtk_signal_connect(GTK_OBJECT (dancer->menu.delete), "activate", GTK_SIGNAL_FUNC (destroy_dancer), dancer); gtk_signal_connect(GTK_OBJECT(dancer->menu.exit), "activate", GTK_SIGNAL_FUNC(disable_gdancer), NULL); // Load pixmaps load_images(dancer); // Make the image-holding widget dancer->pixmap = make_image_widget(dancer); // Set the image to neutral gd_image_change(dancer, 2, 1); // Add the widgets into eachother gtk_container_add (GTK_CONTAINER(dancer->window), dancer->event_box); gtk_container_add (GTK_CONTAINER(dancer->event_box), dancer->pixmap); // Show widget (wouldn't be gdancer without the dancing) // gtk_widget_show (dancer->menu.gblconfig); gtk_widget_show (dancer->menu.config); gtk_widget_show (dancer->menu.about); gtk_widget_show (dancer->menu.raise); gtk_widget_show (dancer->menu.lower); gtk_widget_show (dancer->menu.delete); gtk_widget_show (dancer->menu.add); gtk_widget_show (dancer->menu.exit); // We apply the modified style on every dancer widgets. gtk_widget_set_style(dancer->pixmap, dancer->style); gtk_widget_set_style(dancer->event_box, dancer->style); gtk_widget_set_style(dancer->window, dancer->style); gtk_widget_show (dancer->pixmap); gtk_widget_show (dancer->event_box); gtk_widget_show (dancer->window); return dancer; } void gd_get_new_dancer (void) { GDancer *dancer; dancer = gd_get_new_dancer_with_theme (DEFAULT_THEME); dancer->skip_frames = 3; } static void gnome_wm_set_window_sticky(GtkWidget *window, gboolean sticky) { XEvent xev; gint prev_error; CARD32 state = 0; if (sticky) state = WIN_STATE_STICKY; prev_error = gdk_error_warnings; gdk_error_warnings = 0; if (GTK_WIDGET_MAPPED(window)) { xev.type = ClientMessage; xev.xclient.type = ClientMessage; xev.xclient.window = GDK_WINDOW_XWINDOW(window->window); xev.xclient.message_type = _XA_WIN_STATE; xev.xclient.format = 32; xev.xclient.data.l[0] = WIN_STATE_STICKY; xev.xclient.data.l[1] = state; xev.xclient.data.l[2] = gdk_time_get(); XSendEvent(GDK_DISPLAY(), GDK_ROOT_WINDOW(), False, SubstructureNotifyMask, (XEvent *) & xev); } else { long data[2]; data[0] = state; XChangeProperty(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window->window), _XA_WIN_STATE, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) data, 1); } gdk_error_warnings = prev_error; }