📄 changedisplay.c
字号:
/* Change Display * * Demonstrates migrating a window between different displays and * screens. A display is a mouse and keyboard with some number of * associated monitors. A screen is a set of monitors grouped * into a single physical work area. The neat thing about having * multiple displays is that they can be on a completely separate * computers, as long as there is a network connection to the * computer where the application is running. * * Only some of the windowing systems where GTK+ runs have the * concept of multiple displays and screens. (The X Window System * is the main example.) Other windowing systems can only * handle one keyboard and mouse, and combine all monitors into * a single screen. * * This is a moderately complex example, and demonstrates: * * - Tracking the currently open displays and screens * * - Changing the screen for a window * * - Letting the user choose a window by clicking on it * * - Using GtkListStore and GtkTreeView * * - Using GtkDialog */#include <string.h>#include <gtk/gtk.h>#include "demo-common.h"/* The ChangeDisplayInfo structure corresponds to a toplevel window and * holds pointers to widgets inside the toplevel window along with other * information about the contents of the window. * This is a common organizational structure in real applications. */typedef struct _ChangeDisplayInfo ChangeDisplayInfo;struct _ChangeDisplayInfo{ GtkWidget *window; GtkSizeGroup *size_group; GtkTreeModel *display_model; GtkTreeModel *screen_model; GtkTreeSelection *screen_selection; GdkDisplay *current_display; GdkScreen *current_screen;};/* These enumerations provide symbolic names for the columns * in the two GtkListStore models. */enum{ DISPLAY_COLUMN_NAME, DISPLAY_COLUMN_DISPLAY, DISPLAY_NUM_COLUMNS};enum{ SCREEN_COLUMN_NUMBER, SCREEN_COLUMN_SCREEN, SCREEN_NUM_COLUMNS};/* Finds the toplevel window under the mouse pointer, if any. */static GtkWidget *find_toplevel_at_pointer (GdkDisplay *display){ GdkWindow *pointer_window; GtkWidget *widget = NULL; pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL); /* The user data field of a GdkWindow is used to store a pointer * to the widget that created it. */ if (pointer_window) gdk_window_get_user_data (pointer_window, (gpointer*) &widget); return widget ? gtk_widget_get_toplevel (widget) : NULL;}static gbooleanbutton_release_event_cb (GtkWidget *widget, GdkEventButton *event, gboolean *clicked){ *clicked = TRUE; return TRUE;}/* Asks the user to click on a window, then waits for them click * the mouse. When the mouse is released, returns the toplevel * window under the pointer, or NULL, if there is none. */static GtkWidget *query_for_toplevel (GdkScreen *screen, const char *prompt){ GdkDisplay *display = gdk_screen_get_display (screen); GtkWidget *popup, *label, *frame; GdkCursor *cursor; GtkWidget *toplevel = NULL; popup = gtk_window_new (GTK_WINDOW_POPUP); gtk_window_set_screen (GTK_WINDOW (popup), screen); gtk_window_set_modal (GTK_WINDOW (popup), TRUE); gtk_window_set_position (GTK_WINDOW (popup), GTK_WIN_POS_CENTER); frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_container_add (GTK_CONTAINER (popup), frame); label = gtk_label_new (prompt); gtk_misc_set_padding (GTK_MISC (label), 10, 10); gtk_container_add (GTK_CONTAINER (frame), label); gtk_widget_show_all (popup); cursor = gdk_cursor_new_for_display (display, GDK_CROSSHAIR); if (gdk_pointer_grab (popup->window, FALSE, GDK_BUTTON_RELEASE_MASK, NULL, cursor, GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS) { gboolean clicked = FALSE; g_signal_connect (popup, "button-release-event", G_CALLBACK (button_release_event_cb), &clicked); /* Process events until clicked is set by button_release_event_cb. * We pass in may_block=TRUE since we want to wait if there * are no events currently. */ while (!clicked) g_main_context_iteration (NULL, TRUE); toplevel = find_toplevel_at_pointer (gdk_screen_get_display (screen)); if (toplevel == popup) toplevel = NULL; } gdk_cursor_unref (cursor); gtk_widget_destroy (popup); gdk_flush (); /* Really release the grab */ return toplevel;}/* Prompts the user for a toplevel window to move, and then moves * that window to the currently selected display */static voidquery_change_display (ChangeDisplayInfo *info){ GdkScreen *screen = gtk_widget_get_screen (info->window); GtkWidget *toplevel; toplevel = query_for_toplevel (screen, "Please select the toplevel\n" "to move to the new screen"); if (toplevel) gtk_window_set_screen (GTK_WINDOW (toplevel), info->current_screen); else gdk_display_beep (gdk_screen_get_display (screen));}/* Fills in the screen list based on the current display */static voidfill_screens (ChangeDisplayInfo *info){ gtk_list_store_clear (GTK_LIST_STORE (info->screen_model)); if (info->current_display) { gint n_screens = gdk_display_get_n_screens (info->current_display); gint i; for (i = 0; i < n_screens; i++) { GdkScreen *screen = gdk_display_get_screen (info->current_display, i); GtkTreeIter iter; gtk_list_store_append (GTK_LIST_STORE (info->screen_model), &iter); gtk_list_store_set (GTK_LIST_STORE (info->screen_model), &iter, SCREEN_COLUMN_NUMBER, i, SCREEN_COLUMN_SCREEN, screen, -1); if (i == 0) gtk_tree_selection_select_iter (info->screen_selection, &iter); } }}/* Called when the user clicks on a button in our dialog or * closes the dialog through the window manager. Unless the * "Change" button was clicked, we destroy the dialog. */static voidresponse_cb (GtkDialog *dialog, gint response_id, ChangeDisplayInfo *info){ if (response_id == GTK_RESPONSE_OK) query_change_display (info); else gtk_widget_destroy (GTK_WIDGET (dialog));}/* Called when the user clicks on "Open..." in the display * frame. Prompts for a new display, and then opens a connection * to that display. */static voidopen_display_cb (GtkWidget *button, ChangeDisplayInfo *info){ GtkWidget *dialog; GtkWidget *display_entry; GtkWidget *dialog_label; gchar *new_screen_name = NULL; GdkDisplay *result = NULL; dialog = gtk_dialog_new_with_buttons ("Open Display", GTK_WINDOW (info->window), GTK_DIALOG_MODAL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); display_entry = gtk_entry_new (); gtk_entry_set_activates_default (GTK_ENTRY (display_entry), TRUE); dialog_label = gtk_label_new ("Please enter the name of\nthe new display\n"); gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), dialog_label); gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), display_entry); gtk_widget_grab_focus (display_entry); gtk_widget_show_all (GTK_BIN (dialog)->child); while (!result) { gint response_id = gtk_dialog_run (GTK_DIALOG (dialog)); if (response_id != GTK_RESPONSE_OK) break; new_screen_name = gtk_editable_get_chars (GTK_EDITABLE (display_entry), 0, -1); if (strcmp (new_screen_name, "") != 0) { result = gdk_display_open (new_screen_name); if (!result) { gchar *error_msg = g_strdup_printf ("Can't open display :\n\t%s\nplease try another one\n", new_screen_name); gtk_label_set_text (GTK_LABEL (dialog_label), error_msg); g_free (error_msg); } g_free (new_screen_name); } } gtk_widget_destroy (dialog);}/* Called when the user clicks on the "Close" button in the * "Display" frame. Closes the selected display. */static voidclose_display_cb (GtkWidget *button, ChangeDisplayInfo *info){ if (info->current_display) gdk_display_close (info->current_display);}/* Called when the selected row in the display list changes. * Updates info->current_display, then refills the list of * screens. */static voiddisplay_changed_cb (GtkTreeSelection *selection, ChangeDisplayInfo *info){ GtkTreeModel *model; GtkTreeIter iter; if (info->current_display) g_object_unref (info->current_display); if (gtk_tree_selection_get_selected (selection, &model, &iter)) gtk_tree_model_get (model, &iter, DISPLAY_COLUMN_DISPLAY, &info->current_display, -1); else info->current_display = NULL; fill_screens (info);}/* Called when the selected row in the sceen list changes. * Updates info->current_screen. */static voidscreen_changed_cb (GtkTreeSelection *selection, ChangeDisplayInfo *info)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -