pidgin/gtkrequest.c

branch
release-2.x.y
changeset 39010
fbce915a7024
parent 38266
7c1706b2bd11
child 39011
a2b3cc337c5e
equal deleted inserted replaced
38982:45020dd8cbd9 39010:fbce915a7024
34 #include "gtkimhtmltoolbar.h" 34 #include "gtkimhtmltoolbar.h"
35 #include "gtkrequest.h" 35 #include "gtkrequest.h"
36 #include "gtkutils.h" 36 #include "gtkutils.h"
37 #include "pidginstock.h" 37 #include "pidginstock.h"
38 #include "gtkblist.h" 38 #include "gtkblist.h"
39 #ifdef USE_VV
40 #include "media-gst.h"
41 #endif
39 42
40 #include <gdk/gdkkeysyms.h> 43 #include <gdk/gdkkeysyms.h>
41 44
42 static GtkWidget * create_account_field(PurpleRequestField *field); 45 static GtkWidget * create_account_field(PurpleRequestField *field);
43 46
1701 gtk_widget_show(dirsel); 1704 gtk_widget_show(dirsel);
1702 1705
1703 return (void *)data; 1706 return (void *)data;
1704 } 1707 }
1705 1708
1709 #ifdef USE_VV
1710 static GstElement *create_screensrc_cb(PurpleMedia *media, const gchar *session_id,
1711 const gchar *participant);
1712
1713 #ifdef HAVE_X11
1714 static gboolean
1715 grab_event (GtkWidget *child, GdkEvent *event, PidginRequestData *data)
1716 {
1717 GdkScreen *screen = gdk_screen_get_default();
1718 GObject *info;
1719 GdkWindow *gdkroot = gdk_get_default_root_window();
1720 Window xroot = GDK_WINDOW_XID(gdkroot), xwindow, parent, *children;
1721 unsigned int nchildren, xmask;
1722 Display *xdisplay = GDK_SCREEN_XDISPLAY(screen);
1723 int rootx, rooty, winx, winy;
1724
1725 if (event->type != GDK_BUTTON_PRESS)
1726 return FALSE;
1727
1728 XQueryPointer(xdisplay, xroot, &xroot, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
1729
1730 gdk_pointer_ungrab(GDK_CURRENT_TIME);
1731
1732 /* Find WM window (direct child of root) */
1733 while (1) {
1734 if (!XQueryTree(xdisplay, xwindow, &xroot, &parent, &children, &nchildren))
1735 break;
1736
1737 if (nchildren)
1738 XFree(children);
1739
1740 if (xroot == parent)
1741 break;
1742
1743 xwindow = parent;
1744 }
1745
1746 generic_response_start(data);
1747
1748 if (data->cbs[0] != NULL) {
1749 info = g_object_new(PURPLE_TYPE_MEDIA_ELEMENT_INFO,
1750 "id", "screenshare-window",
1751 "name", "Screen share single window",
1752 "type", PURPLE_MEDIA_ELEMENT_VIDEO | PURPLE_MEDIA_ELEMENT_SRC |
1753 PURPLE_MEDIA_ELEMENT_ONE_SRC,
1754 "create-cb", create_screensrc_cb, NULL);
1755 g_object_set_data(info, "window-id", GUINT_TO_POINTER(xwindow));
1756 ((PurpleRequestScreenshareCb)data->cbs[0])(data->user_data, info);
1757 }
1758
1759 purple_request_close(PURPLE_REQUEST_SCREENSHARE, data);
1760
1761 return FALSE;
1762 }
1763
1764 static void
1765 screenshare_window_cb(GtkWidget *button, PidginRequestData *data)
1766 {
1767 GdkCursor *cursor;
1768 GdkWindow *gdkwin = gtk_widget_get_window(GTK_WIDGET(data->dialog));
1769
1770 if (!GTK_WIDGET_HAS_FOCUS(button))
1771 gtk_widget_grab_focus(button);
1772
1773 gtk_widget_add_events(GTK_WIDGET(data->dialog),
1774 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
1775 g_signal_connect(data->dialog, "event", G_CALLBACK(grab_event), data);
1776
1777 cursor = gdk_cursor_new(GDK_CROSSHAIR);
1778 gdk_pointer_grab(gdkwin, FALSE,
1779 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK,
1780 NULL, cursor, GDK_CURRENT_TIME);
1781 }
1782
1783 static GstElement *create_screensrc_cb(PurpleMedia *media, const gchar *session_id,
1784 const gchar *participant)
1785 {
1786 GObject *info;
1787 GstElement *ret;
1788
1789 ret = gst_element_factory_make("ximagesrc", NULL);
1790 g_object_set(ret, "use-damage", 0, NULL);
1791
1792 info = g_object_get_data(G_OBJECT(media), "src-element");
1793 if (info) {
1794 Window xid = GPOINTER_TO_UINT(g_object_get_data(info, "window-id"));
1795 int monitor_no = GPOINTER_TO_INT(g_object_get_data(info, "monitor-no"));
1796 if (xid) {
1797 g_object_set(ret, "xid", xid, NULL);
1798 } else if (monitor_no >= 0) {
1799 GdkScreen *screen = gdk_screen_get_default();
1800 GdkRectangle geom;
1801
1802 gdk_screen_get_monitor_geometry(screen, monitor_no, &geom);
1803 g_object_set(ret, "startx", geom.x, "starty", geom.y,
1804 "endx", geom.x + geom.width - 1,
1805 "endy", geom.y + geom.height - 1, NULL);
1806 }
1807 }
1808
1809 return ret;
1810 }
1811 #elif defined (_WIN32)
1812 static GstElement *create_screensrc_cb(PPurpleMedia *media, const gchar *session_id,
1813 const gchar *participant)
1814 {
1815 GObject *info;
1816 GstElement *ret;
1817
1818 ret = gst_element_factory_make("gdiscreencapsrc", NULL);
1819 g_object_set(ret, "cursor", TRUE);
1820
1821 info = g_object_get_data(G_OBJECT(media), "src-element");
1822 if (info) {
1823 int monitor_no = GPOINTER_TO_INT(g_object_get_data(info, "monitor-no"));
1824 if (monitor_no >= 0)
1825 g_object_set(ret, "monitor", monitor_no);
1826 }
1827
1828 return ret;
1829 }
1830 #else
1831 /* We don't actually need to break the build just because we can't do
1832 * screencap, but gtkmedia.c is going to break the USE_VV build if it
1833 * isn't WIN32 or X11 anyway, so we might as well. */
1834 #error "Unsupported windowing system"
1835 #endif
1836
1837 static void
1838 screenshare_monitor_cb(GtkWidget *button, PidginRequestData *data)
1839 {
1840 GtkWidget *radio;
1841 GObject *info;
1842 int monitor_no = -1;
1843
1844 generic_response_start(data);
1845
1846 if (!GTK_WIDGET_HAS_FOCUS(button))
1847 gtk_widget_grab_focus(button);
1848
1849 radio = g_object_get_data(G_OBJECT(data->dialog), "radio");
1850 if (radio) {
1851 GSList *group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));
1852
1853 while (group) {
1854 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group->data))) {
1855 monitor_no = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(group->data),
1856 "monitor-no"));
1857 break;
1858 }
1859 group = group->next;
1860 }
1861 }
1862 if (data->cbs[0] != NULL) {
1863 info = g_object_new(PURPLE_TYPE_MEDIA_ELEMENT_INFO,
1864 "id", "screenshare-monitor",
1865 "name", "Screen share monitor",
1866 "type", PURPLE_MEDIA_ELEMENT_VIDEO | PURPLE_MEDIA_ELEMENT_SRC |
1867 PURPLE_MEDIA_ELEMENT_ONE_SRC,
1868 "create-cb", create_screensrc_cb, NULL);
1869 g_object_set_data(info, "monitor-no", GINT_TO_POINTER(monitor_no));
1870 ((PurpleRequestScreenshareCb)data->cbs[0])(data->user_data, info);
1871 }
1872
1873 purple_request_close(PURPLE_REQUEST_SCREENSHARE, data);
1874 }
1875
1876 static GstElement *create_videotest_cb(PurpleMedia *media, const gchar *session_id,
1877 const gchar *participant)
1878 {
1879 return gst_element_factory_make("videotestsrc", NULL);
1880 }
1881
1882 static void
1883 screenshare_videotest_cb(GtkWidget *button, PidginRequestData *data)
1884 {
1885 GObject *info;
1886
1887 generic_response_start(data);
1888
1889 if (!GTK_WIDGET_HAS_FOCUS(button))
1890 gtk_widget_grab_focus(button);
1891
1892 if (data->cbs[0] != NULL) {
1893 info = g_object_new(PURPLE_TYPE_MEDIA_ELEMENT_INFO,
1894 "id", "screenshare-videotestsrc",
1895 "name", "Screen share test source",
1896 "type", PURPLE_MEDIA_ELEMENT_VIDEO | PURPLE_MEDIA_ELEMENT_SRC |
1897 PURPLE_MEDIA_ELEMENT_ONE_SRC,
1898 "create-cb", create_videotest_cb, NULL);
1899 ((PurpleRequestScreenshareCb)data->cbs[0])(data->user_data, info);
1900 }
1901
1902 purple_request_close(PURPLE_REQUEST_SCREENSHARE, data);
1903 }
1904
1905 static void
1906 screenshare_cancel_cb(GtkWidget *button, PidginRequestData *data)
1907 {
1908 generic_response_start(data);
1909
1910 if (data->cbs[0] != NULL)
1911 ((PurpleRequestScreenshareCb)data->cbs[0])(data->user_data, NULL);
1912
1913 purple_request_close(PURPLE_REQUEST_SCREENSHARE, data);
1914 }
1915
1916 static gboolean
1917 destroy_screenshare_cb(GtkWidget *dialog, GdkEvent *event,
1918 PidginRequestData *data)
1919 {
1920 screenshare_cancel_cb(NULL, data);
1921 return FALSE;
1922 }
1923
1924 static void *pidgin_request_screenshare_media(const char *title, const char *primary,
1925 const char *secondary, PurpleAccount *account,
1926 GCallback cb, void *user_data)
1927 {
1928 PidginRequestData *data;
1929 GtkWidget *dialog;
1930 GtkWidget *vbox;
1931 GtkWidget *hbox;
1932 GtkWidget *label;
1933 GtkWidget *button;
1934 GtkWidget *radio = NULL;
1935 GdkScreen *screen;
1936 char *label_text;
1937 char *primary_esc, *secondary_esc;
1938
1939 data = g_new0(PidginRequestData, 1);
1940 data->type = PURPLE_REQUEST_SCREENSHARE;
1941 data->user_data = user_data;
1942
1943 data->cb_count = 1;
1944 data->cbs = g_new0(GCallback, 1);
1945 data->cbs[0] = cb;
1946
1947 /* Create the dialog. */
1948 data->dialog = dialog = gtk_dialog_new();
1949
1950 if (title != NULL)
1951 gtk_window_set_title(GTK_WINDOW(dialog), title);
1952 #ifdef _WIN32
1953 else
1954 gtk_window_set_title(GTK_WINDOW(dialog), PIDGIN_ALERT_TITLE);
1955 #endif
1956
1957 button = pidgin_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL,
1958 G_CALLBACK(screenshare_cancel_cb), data);
1959 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1960
1961 if (g_getenv("PIDGIN_SHARE_VIDEOTEST") != NULL) {
1962 button = pidgin_dialog_add_button(GTK_DIALOG(dialog), _("Test image"),
1963 G_CALLBACK(screenshare_videotest_cb), data);
1964 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1965 gtk_window_set_default(GTK_WINDOW(dialog), button);
1966 }
1967
1968 #ifdef HAVE_X11
1969 button = pidgin_dialog_add_button(GTK_DIALOG(dialog), _("Select window"),
1970 G_CALLBACK(screenshare_window_cb), data);
1971 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1972 gtk_window_set_default(GTK_WINDOW(dialog), button);
1973 #endif
1974
1975 button = pidgin_dialog_add_button(GTK_DIALOG(dialog), _("Use monitor"),
1976 G_CALLBACK(screenshare_monitor_cb), data);
1977 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1978 gtk_window_set_default(GTK_WINDOW(dialog), button);
1979
1980 g_signal_connect(G_OBJECT(dialog), "delete_event",
1981 G_CALLBACK(destroy_screenshare_cb), data);
1982
1983 /* Setup the dialog */
1984 gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER/2);
1985 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2);
1986 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
1987 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
1988 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER);
1989
1990 /* Setup the main horizontal box */
1991 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
1992 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
1993
1994
1995 /* Vertical box */
1996 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
1997 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
1998
1999 pidgin_widget_decorate_account(hbox, account);
2000
2001 /* Descriptive label */
2002 primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL;
2003 secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL;
2004 label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">"
2005 "%s</span>%s%s" : "%s%s%s"),
2006 (primary ? primary_esc : ""),
2007 ((primary && secondary) ? "\n\n" : ""),
2008 (secondary ? secondary_esc : ""));
2009 g_free(primary_esc);
2010 g_free(secondary_esc);
2011
2012 label = gtk_label_new(NULL);
2013
2014 gtk_label_set_markup(GTK_LABEL(label), label_text);
2015 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
2016 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
2017 gtk_label_set_selectable(GTK_LABEL(label), TRUE);
2018 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
2019
2020 g_free(label_text);
2021
2022 screen = gdk_screen_get_default();
2023 if (screen) {
2024 int nr_monitors = gdk_screen_get_n_monitors(screen);
2025 int primary = gdk_screen_get_primary_monitor(screen);
2026 int i;
2027
2028 for (i = 0; i < nr_monitors; i++) {
2029 GdkRectangle geom;
2030 gchar *name;
2031 gchar *label;
2032
2033 name = gdk_screen_get_monitor_plug_name(screen, i);
2034 gdk_screen_get_monitor_geometry(screen, i, &geom);
2035
2036 label = g_strdup_printf(_("%s (%d✕%d @ %d,%d)"),
2037 name ? name : _("Unknown output"),
2038 geom.width, geom.height,
2039 geom.x, geom.y);
2040 radio = gtk_radio_button_new_with_label_from_widget((GtkRadioButton *)radio, label);
2041 g_object_set_data(G_OBJECT(radio), "monitor-no", GINT_TO_POINTER(i));
2042 gtk_box_pack_start(GTK_BOX(vbox), radio, FALSE, FALSE, 0);
2043 if (i == primary)
2044 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
2045
2046 g_free(label);
2047 g_free(name);
2048 }
2049 g_object_set_data(G_OBJECT(dialog), "radio", radio);
2050 }
2051
2052 /* Show everything. */
2053 pidgin_auto_parent_window(dialog);
2054
2055 gtk_widget_show_all(dialog);
2056
2057 return data;
2058
2059 }
2060 #endif /* USE_VV */
2061
1706 static void 2062 static void
1707 pidgin_close_request(PurpleRequestType type, void *ui_handle) 2063 pidgin_close_request(PurpleRequestType type, void *ui_handle)
1708 { 2064 {
1709 PidginRequestData *data = (PidginRequestData *)ui_handle; 2065 PidginRequestData *data = (PidginRequestData *)ui_handle;
1710 2066
1728 pidgin_request_fields, 2084 pidgin_request_fields,
1729 pidgin_request_file, 2085 pidgin_request_file,
1730 pidgin_close_request, 2086 pidgin_close_request,
1731 pidgin_request_folder, 2087 pidgin_request_folder,
1732 pidgin_request_action_with_icon, 2088 pidgin_request_action_with_icon,
2089 #ifdef USE_VV
2090 pidgin_request_screenshare_media,
2091 #else
1733 NULL, 2092 NULL,
2093 #endif
1734 NULL, 2094 NULL,
1735 NULL 2095 NULL
1736 }; 2096 };
1737 2097
1738 PurpleRequestUiOps * 2098 PurpleRequestUiOps *

mercurial