aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkraxel <kraxel>2007-07-18 08:19:06 +0000
committerkraxel <kraxel>2007-07-18 08:19:06 +0000
commit1abb391559d2a32ada784390952abd2536786312 (patch)
tree3769c332ce7efb4a8dbcf50b1941177b7b0ae6ed
parent490c34d9eb570a9e21d9a984491411e6bde6e433 (diff)
downloadxenwatch-1abb391559d2a32ada784390952abd2536786312.tar.gz
vnc polishing
-rw-r--r--vnc-client.c6
-rw-r--r--vnc.c317
-rw-r--r--vnc.h1
3 files changed, 254 insertions, 70 deletions
diff --git a/vnc-client.c b/vnc-client.c
index 331fc86..56599f6 100644
--- a/vnc-client.c
+++ b/vnc-client.c
@@ -26,6 +26,7 @@ static void usage(FILE *fp)
" -d Enable debug output.\n"
" -u Send us kbd layout keysyms.\n"
" -p Show mouse pointer.\n"
+ " -f Start in fullscreen mode.\n"
" -g Enable OpenGL for fullscreen mode.\n"
" -G Enable OpenGL unconditionally.\n"
" -o View only.\n"
@@ -45,7 +46,7 @@ main(int argc, char *argv[])
gtk_init(&argc, &argv);
for (;;) {
- if (-1 == (c = getopt(argc, argv, "hdupgGo")))
+ if (-1 == (c = getopt(argc, argv, "hdupfgGo")))
break;
switch (c) {
case 'd':
@@ -66,6 +67,9 @@ main(int argc, char *argv[])
case 'G':
vnc_flags |= VNC_FLAG_GL_ALLWAYS;
break;
+ case 'f':
+ vnc_flags |= VNC_FLAG_FULLSCREEN;
+ break;
case 'h':
usage(stdout);
exit(0);
diff --git a/vnc.c b/vnc.c
index 1d8b2bb..8024249 100644
--- a/vnc.c
+++ b/vnc.c
@@ -46,9 +46,12 @@ struct vnc_window {
guint id, connected;
/* gtk */
+ GtkAccelGroup *ac;
+ GtkActionGroup *ag;
+ GtkUIManager *ui;
GtkWidget *win;
GtkWidget *draw;
- GtkWidget *line, *res, *fs, *kbd, *ptr, *view;
+ GtkWidget *line, *res, *mbutton, *popup;
GdkCursor *on,*off;
int filter_installed;
int input_grabbed;
@@ -99,6 +102,7 @@ static int linux_uskbd_size = sizeof(linux_uskbd)/sizeof(linux_uskbd[0]);
static GdkFilterReturn event_filter(GdkXEvent *gdkxevent, GdkEvent *gtkevent,
gpointer data);
static void vnc_window_conf(struct vnc_window *vnc);
+static void vnc_window_texts(struct vnc_window *vnc);
/* ------------------------------------------------------------------ */
/* opengl bits */
@@ -470,6 +474,8 @@ static void dpy_setup(struct vnc_window *vnc, int width, int height, int using_g
fprintf(stderr, "%s: SetFormatAndEncodings: %s\n", __FUNCTION__,
using_gl ? "GL" : "X11" );
SetFormatAndEncodings(vnc->client);
+ SendFramebufferUpdateRequest(vnc->client, 0, 0,
+ vnc->vncdpy.w, vnc->vncdpy.h, False);
vnc_window_conf(vnc);
}
@@ -491,6 +497,7 @@ static void dpy_resize_window(struct vnc_window *vnc)
gl_resize_window(vnc);
dpy_redraw(vnc);
}
+ vnc_window_texts(vnc);
}
/* ------------------------------------------------------------------ */
@@ -521,6 +528,7 @@ static GdkCursor* empty_cursor(void)
static void vnc_window_texts(struct vnc_window *vnc)
{
char textline[256];
+ int pos;
if (vnc->client && vnc->client->desktopName &&
strlen(vnc->client->desktopName)) {
@@ -541,25 +549,23 @@ static void vnc_window_texts(struct vnc_window *vnc)
}
if (vnc->client) {
- snprintf(textline, sizeof(textline), "%dx%d",
- vnc->vncdpy.w, vnc->vncdpy.h);
+ pos = 0;
+ pos += snprintf(textline+pos, sizeof(textline)-pos, "%dx%d",
+ vnc->vncdpy.w, vnc->vncdpy.h);
+ if (vnc->vncdpy.w != vnc->window.w ||
+ vnc->vncdpy.h != vnc->window.h)
+ pos += snprintf(textline+pos, sizeof(textline)-pos, " @ %dx%d",
+ vnc->window.w, vnc->window.h);
+ pos += snprintf(textline+pos, sizeof(textline)-pos, " (%s)",
+ vnc->ximage ? "X11" : "GL");
gtk_label_set_text(GTK_LABEL(vnc->res), textline);
}
- gtk_button_set_label(GTK_BUTTON(vnc->fs),
- vnc->fullscreen ? "FS: on" : "FS: off");
- gtk_button_set_label(GTK_BUTTON(vnc->kbd),
- vnc->uskbd ? "kbd: us" : "kbd: local");
- gtk_button_set_label(GTK_BUTTON(vnc->ptr),
- vnc->showpointer ? "ptr: visible" : "ptr: hidden");
- gtk_button_set_label(GTK_BUTTON(vnc->view),
- vnc->viewonly ? "viewonly" : "input ok");
}
static void vnc_window_conf(struct vnc_window *vnc)
{
if (!vnc->draw)
return;
- vnc_window_texts(vnc);
if (vnc->client)
gtk_widget_set_size_request(vnc->draw, vnc->vncdpy.w, vnc->vncdpy.h);
if (vnc->draw->window) {
@@ -805,13 +811,15 @@ static gboolean window_state_cb(GtkWidget *widget, GdkEventWindowState *event,
gpointer data)
{
struct vnc_window *vnc = data;
+ GtkWidget *item;
if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
vnc->fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;
if (vnc->debug)
fprintf(stderr, "%s: fullscreen %s\n", __FUNCTION__,
vnc->fullscreen ? "on" : "off");
- vnc_window_texts(vnc);
+ item = gtk_ui_manager_get_widget(vnc->ui, "/ConfMenu/FullScreen");
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), vnc->fullscreen);
}
return TRUE;
}
@@ -860,7 +868,21 @@ static void send_mouse(struct vnc_window *vnc, int x, int y,
rfbstate &= ~buttons[i].rfbmask;
}
- /* FIXME: fixup mouse coordinates */
+ /* fixup mouse coordinates */
+ x -= vnc->vncoff.x;
+ y -= vnc->vncoff.y;
+ if (vnc->tex) {
+ x = x * vnc->window.w / vnc->vncdpy.w;
+ y = y * vnc->window.h / vnc->vncdpy.h;
+ }
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ if (x >= vnc->vncdpy.w)
+ x = vnc->vncdpy.w -1;
+ if (y >= vnc->vncdpy.h)
+ y = vnc->vncdpy.h -1;
if (vnc->debug)
fprintf(stderr,"%s: +%d+%d x11state 0x%x rfbstate 0x%x\n",
@@ -952,42 +974,12 @@ static gboolean key_cb(GtkWidget *widget, GdkEventKey *event,
return TRUE;
}
-static void fs_btn(GtkWidget *widget, gpointer data)
-{
- struct vnc_window *vnc = data;
-
- vnc->fullscreen = !vnc->fullscreen;
- if (vnc->fullscreen)
- gtk_window_fullscreen(GTK_WINDOW(vnc->win));
- else
- gtk_window_unfullscreen(GTK_WINDOW(vnc->win));
-}
-
-static void kbd_btn(GtkWidget *widget, gpointer data)
+static void menu_btn(GtkWidget *widget, gpointer data)
{
struct vnc_window *vnc = data;
- vnc->uskbd = !vnc->uskbd;
- vnc_window_texts(vnc);
-}
-
-static void ptr_btn(GtkWidget *widget, gpointer data)
-{
- struct vnc_window *vnc = data;
-
- vnc->showpointer = !vnc->showpointer;
- if (vnc->draw->window)
- gdk_window_set_cursor(vnc->draw->window,
- vnc->showpointer ? vnc->on : vnc->off);
- vnc_window_texts(vnc);
-}
-
-static void view_btn(GtkWidget *widget, gpointer data)
-{
- struct vnc_window *vnc = data;
-
- vnc->viewonly = !vnc->viewonly;
- vnc_window_texts(vnc);
+ gtk_menu_popup(GTK_MENU(vnc->popup), NULL, NULL, NULL, NULL,
+ 0, gtk_get_current_event_time());
}
static GdkFilterReturn event_filter(GdkXEvent *gdkxevent, GdkEvent *gtkevent,
@@ -1031,12 +1023,174 @@ static GdkFilterReturn event_filter(GdkXEvent *gdkxevent, GdkEvent *gtkevent,
}
/* ------------------------------------------------------------------ */
+
+static void menu_cb_full_screen(GtkToggleAction *action, gpointer user_data)
+{
+ struct vnc_window *vnc = user_data;
+
+ vnc->fullscreen = gtk_toggle_action_get_active(action);
+ if (vnc->fullscreen)
+ gtk_window_fullscreen(GTK_WINDOW(vnc->win));
+ else
+ gtk_window_unfullscreen(GTK_WINDOW(vnc->win));
+}
+
+static void menu_cb_us_keyboard(GtkToggleAction *action, gpointer user_data)
+{
+ struct vnc_window *vnc = user_data;
+
+ vnc->uskbd = gtk_toggle_action_get_active(action);
+}
+
+static void menu_cb_show_pointer(GtkToggleAction *action, gpointer user_data)
+{
+ struct vnc_window *vnc = user_data;
+
+ vnc->showpointer = gtk_toggle_action_get_active(action);
+ if (vnc->draw->window)
+ gdk_window_set_cursor(vnc->draw->window,
+ vnc->showpointer ? vnc->on : vnc->off);
+}
+
+static void menu_cb_view_only(GtkToggleAction *action, gpointer user_data)
+{
+ struct vnc_window *vnc = user_data;
+
+ vnc->viewonly = gtk_toggle_action_get_active(action);
+}
+
+static void menu_cb_gl(GtkRadioAction *action, GtkRadioAction *current,
+ gpointer user_data)
+{
+ struct vnc_window *vnc = user_data;
+ int value = gtk_radio_action_get_current_value(action);
+
+ switch (value) {
+ case 1: /* OFF */
+ vnc->gl_fullscreen = 0;
+ vnc->gl_allways = 0;
+ break;
+ case 2: /* fullscreen ON */
+ vnc->gl_fullscreen = 1;
+ vnc->gl_allways = 0;
+ break;
+ case 3: /* allways ON */
+ vnc->gl_fullscreen = 1;
+ vnc->gl_allways = 1;
+ break;
+ }
+ dpy_resize_window(vnc);
+}
+
+static void menu_cb_about(GtkMenuItem *item, void *user_data)
+{
+ static char *comments = "simple vnc client";
+ static char *copyright = "(c) 2005-2007 Gerd Hoffmann";
+ static char *authors[] = { "Gerd Hoffmann <kraxel@redhat.com>", NULL };
+ struct vnc_window *vnc = user_data;
+
+ gtk_show_about_dialog(GTK_WINDOW(vnc->win),
+ "authors", authors,
+ "comments", comments,
+ "copyright", copyright,
+ "logo-icon-name", GTK_STOCK_ABOUT,
+ "version", VERSION,
+ NULL);
+}
+
+static void menu_cb_quit(GtkMenuItem *item, void *user_data)
+{
+ struct vnc_window *vnc = user_data;
+
+ gtk_widget_destroy(vnc->win);
+}
+
+/* ------------------------------------------------------------------ */
+
+static const GtkActionEntry entries[] = {
+ {
+ /* popup menu */
+ .name = "ConfMenu",
+ .label = "Config",
+ },{
+ /* menu items */
+ .name = "About",
+ .stock_id = GTK_STOCK_ABOUT,
+ .label = "_About ...",
+ .callback = G_CALLBACK(menu_cb_about),
+ },{
+ .name = "Close",
+ .stock_id = GTK_STOCK_QUIT,
+ .label = "_Close",
+// .accelerator = "<control>Q",
+ .tooltip = "Quit the job",
+ .callback = G_CALLBACK(menu_cb_quit),
+ }
+};
+
+static const GtkToggleActionEntry tentries[] = {
+ {
+ .name = "FullScreen",
+ .label = "_Fullscreen",
+ .accelerator = "F11",
+ .callback = G_CALLBACK(menu_cb_full_screen),
+ },{
+ .name = "USKbd",
+ .label = "US _Keyboard",
+ .callback = G_CALLBACK(menu_cb_us_keyboard),
+ },{
+ .name = "ShowPointer",
+ .label = "Show _Pointer",
+ .callback = G_CALLBACK(menu_cb_show_pointer),
+ },{
+ .name = "ViewOnly",
+ .label = "_View only",
+ .callback = G_CALLBACK(menu_cb_view_only),
+ }
+};
+
+static const GtkRadioActionEntry rentries[] = {
+ {
+ .name = "GL_OFF",
+ .label = "_Disable OpenGL scaling",
+ .value = 1,
+ },{
+ .name = "GL_FSonly",
+ .label = "OpenGL scaling for fullscreen",
+ .value = 2,
+ },{
+ .name = "GL_ON",
+ .label = "Allways scale using _OpenGL",
+ .value = 3,
+ }
+};
+
+static char ui_xml[] =
+"<ui>"
+" <popup action='ConfMenu'>"
+" <menuitem action='FullScreen'/>"
+" <menuitem action='USKbd'/>"
+" <menuitem action='ShowPointer'/>"
+" <menuitem action='ViewOnly'/>"
+" <separator/>"
+" <menuitem action='GL_OFF'/>"
+" <menuitem action='GL_FSonly'/>"
+" <menuitem action='GL_ON'/>"
+" <separator/>"
+" <menuitem action='About'/>"
+" <menuitem action='Close'/>"
+" </popup>"
+"</ui>";
+
+/* ------------------------------------------------------------------ */
/* public API functions */
GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags,
int debug_level)
{
- GtkWidget *vbox, *hbox, *frame;
+ GtkWidget *vbox, *hbox, *frame, *item;
+ GtkAction *action;
+ GError *err;
char *argv[] = { "vnc-client", NULL, NULL };
int argc = sizeof(argv)/sizeof(argv[0]) -1;
struct vnc_window *vnc;
@@ -1104,25 +1258,51 @@ GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags,
gdk_window_add_filter(NULL, event_filter, vnc);
vnc->filter_installed = 1;
+ /* popup menu */
+ vnc->ui = gtk_ui_manager_new();
+ vnc->ag = gtk_action_group_new("MenuActions");
+ gtk_action_group_add_actions(vnc->ag, entries, G_N_ELEMENTS(entries), vnc);
+ gtk_action_group_add_toggle_actions(vnc->ag, tentries,
+ G_N_ELEMENTS(tentries), vnc);
+ gtk_action_group_add_radio_actions(vnc->ag, rentries,
+ G_N_ELEMENTS(rentries),
+ 0, G_CALLBACK(menu_cb_gl), vnc);
+ gtk_ui_manager_insert_action_group(vnc->ui, vnc->ag, 0);
+ vnc->ac = gtk_ui_manager_get_accel_group(vnc->ui);
+ gtk_window_add_accel_group(GTK_WINDOW(vnc->win), vnc->ac);
+
+ err = NULL;
+ if (!gtk_ui_manager_add_ui_from_string(vnc->ui, ui_xml, -1, &err)) {
+ g_message("building menus failed: %s", err->message);
+ g_error_free(err);
+ exit(1);
+ }
+ vnc->popup = gtk_ui_manager_get_widget(vnc->ui, "/ConfMenu");
+ gtk_menu_set_title(GTK_MENU(vnc->popup), "Config");
+
+ /* popup menu: initial state */
+ item = gtk_ui_manager_get_widget(vnc->ui, "/ConfMenu/USKbd");
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), vnc->uskbd);
+ item = gtk_ui_manager_get_widget(vnc->ui, "/ConfMenu/ShowPointer");
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), vnc->showpointer);
+ item = gtk_ui_manager_get_widget(vnc->ui, "/ConfMenu/ViewOnly");
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), vnc->viewonly);
+
+ action = gtk_ui_manager_get_action(vnc->ui, "/ConfMenu/GL_ON");
+ if (vnc->gl_allways)
+ gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), 3);
+ else if (vnc->gl_fullscreen)
+ gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), 2);
+ else
+ gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), 1);
+
/* labels for the status line */
vnc->line = gtk_label_new("status line");
vnc->res = gtk_label_new("vnc screen resolution");
- vnc->fs = gtk_button_new_with_label("FS");
- vnc->kbd = gtk_button_new_with_label("keyboard mode");
- vnc->ptr = gtk_button_new_with_label("mouse mode");
- vnc->view = gtk_button_new_with_label("input mode");
- g_signal_connect(G_OBJECT(vnc->fs), "clicked",
- G_CALLBACK(fs_btn), vnc);
- g_signal_connect(G_OBJECT(vnc->kbd), "clicked",
- G_CALLBACK(kbd_btn), vnc);
- g_signal_connect(G_OBJECT(vnc->ptr), "clicked",
- G_CALLBACK(ptr_btn), vnc);
- g_signal_connect(G_OBJECT(vnc->view), "clicked",
- G_CALLBACK(view_btn), vnc);
- GTK_WIDGET_UNSET_FLAGS(vnc->fs, GTK_CAN_FOCUS);
- GTK_WIDGET_UNSET_FLAGS(vnc->kbd, GTK_CAN_FOCUS);
- GTK_WIDGET_UNSET_FLAGS(vnc->ptr, GTK_CAN_FOCUS);
- GTK_WIDGET_UNSET_FLAGS(vnc->view, GTK_CAN_FOCUS);
+ vnc->mbutton = gtk_button_new_with_label("config");
+ g_signal_connect(G_OBJECT(vnc->mbutton), "clicked",
+ G_CALLBACK(menu_btn), vnc);
+ GTK_WIDGET_UNSET_FLAGS(vnc->mbutton, GTK_CAN_FOCUS);
/* packing */
vbox = gtk_vbox_new(FALSE, 0);
@@ -1142,17 +1322,16 @@ GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags,
gtk_container_add(GTK_CONTAINER(frame), vnc->res);
gtk_misc_set_padding(GTK_MISC(vnc->res), 3, 1);
- gtk_box_pack_start(GTK_BOX(hbox), vnc->fs, FALSE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(hbox), vnc->kbd, FALSE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(hbox), vnc->ptr, FALSE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(hbox), vnc->view, FALSE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), vnc->mbutton, FALSE, TRUE, 0);
/* show window */
gtk_widget_show_all(vnc->win);
vnc_window_conf(vnc);
+ if (flags & VNC_FLAG_FULLSCREEN)
+ gtk_window_fullscreen(GTK_WINDOW(vnc->win));
/* opengl */
- if ((vnc->gl_allways || vnc->gl_fullscreen) && 0 == gl_init(vnc))
+ if (0 == gl_init(vnc))
vnc->have_gl = 1;
/* rfb client */
diff --git a/vnc.h b/vnc.h
index 0c5c34c..d97130a 100644
--- a/vnc.h
+++ b/vnc.h
@@ -4,6 +4,7 @@
#define VNC_FLAG_VIEW_ONLY (1 << 4)
#define VNC_FLAG_GL_ALLWAYS (1 << 5)
#define VNC_FLAG_GL_FULLSCR (1 << 6)
+#define VNC_FLAG_FULLSCREEN (1 << 7)
GtkWidget *vnc_open(char *hostname, int tcpport, unsigned long flags,
int debug_level);