From 14d288511323d4f384d4764ab25a42693ff19f4a Mon Sep 17 00:00:00 2001 From: Javier Date: Sat, 17 May 2014 19:53:53 +0200 Subject: gtk3 client library + module now hackishly working --- configure.ac | 63 +++--- libtopmenu-client/Makefile.am | 21 +- libtopmenu-client/topmenu-appmenubar.c | 32 ++++ libtopmenu-client/topmenu-client.c | 6 +- libtopmenu-client/topmenu-monitor.c | 2 +- libtopmenu-server/Makefile.am | 19 +- libtopmenu-server/topmenu-widget.c | 2 +- libtopmenu-server/topmenu-widget.h | 2 +- module/Makefile.am | 2 +- module/data.c | 8 + module/main.c | 10 +- module/menuitem-proxy.c | 338 +++++++++++++++++++++++++++++++-- test/Makefile.am | 4 +- test/client.c | 22 ++- test/server.c | 1 - 15 files changed, 455 insertions(+), 77 deletions(-) diff --git a/configure.ac b/configure.ac index c9623ce..6383e9d 100644 --- a/configure.ac +++ b/configure.ac @@ -31,6 +31,7 @@ AC_ARG_ENABLE([mate-applet], [], [enable_mate_applet=check]) +AM_CONDITIONAL([GTK3], [test GTK$with_gtk = GTK3]) AC_SUBST([GTK_VERSION], [$with_gtk]) AC_DEFINE_UNQUOTED([GTK_VERSION], [$with_gtk], [Define to GTK major version used]) AC_SUBST([GTK_MODULE_DIR], [$with_gtk_module_dir]) @@ -43,37 +44,39 @@ AC_PROG_LIBTOOL # Checks for libraries. PKG_CHECK_MODULES([GTK], [gtk+-x11-$with_gtk.0]) -AS_IF([test "x$with_wnck" = xwnck1 -o "x$with_wnck" = xcheck], - [PKG_CHECK_MODULES([WNCK], [libwnck-1.0], - [ - AC_DEFINE([HAVE_WNCK1], [1], [Define if you have libwnck-1.0]) - with_wnck=libwnck1 - ], - [if test "x$with_wnck" = xwnck1; then - AC_MSG_FAILURE([--with-wnck=wnck1 was given, but test for libwnck-1.0 failed]) - fi] - )]) -AS_IF([test "x$with_wnck" = xmatewnck -o "x$with_wnck" = xcheck], - [PKG_CHECK_MODULES([MATEWNCK], [libmatewnck], - [ - AC_DEFINE([HAVE_MATEWNCK], [1], [Define if you have libmatewnck]) - with_wnck=libmatewnck - ], - [if test "x$with_wnck" = xmatewnck; then - AC_MSG_FAILURE([--with-wnck=matewnck was given, but test for libmatewnck failed]) - fi] - )]) +AS_IF([test "x$with_gtk" = x3], + [], + [AS_IF([test "x$with_wnck" = xwnck1 -o "x$with_wnck" = xcheck], + [PKG_CHECK_MODULES([WNCK], [libwnck-1.0], + [ + AC_DEFINE([HAVE_WNCK1], [1], [Define if you have libwnck-1.0]) + with_wnck=libwnck1 + ], + [if test "x$with_wnck" = xwnck1; then + AC_MSG_FAILURE([--with-wnck=wnck1 was given, but test for libwnck-1.0 failed]) + fi] + )]) + AS_IF([test "x$with_wnck" = xmatewnck -o "x$with_wnck" = xcheck], + [PKG_CHECK_MODULES([MATEWNCK], [libmatewnck], + [ + AC_DEFINE([HAVE_MATEWNCK], [1], [Define if you have libmatewnck]) + with_wnck=libmatewnck + ], + [if test "x$with_wnck" = xmatewnck; then + AC_MSG_FAILURE([--with-wnck=matewnck was given, but test for libmatewnck failed]) + fi] + )]) -AS_IF([test "x$enable_mate_applet" != xno], - [PKG_CHECK_MODULES([MATEPANELAPPLET], [libmatepanelapplet-4.0], - [ - AC_DEFINE([HAVE_MATEPANELAPPLET], [1], [Define if you have libmatepanelapplet]) - enable_mate_applet=yes - ], - [if test "x$enable_mate_applet" = xyes; then - AC_MSG_FAILURE([--enable-mate-applet was given, but test for libmatepanelapplet failed]) - fi] - )]) + AS_IF([test "x$enable_mate_applet" != xno], + [PKG_CHECK_MODULES([MATEPANELAPPLET], [libmatepanelapplet-4.0], + [ + AC_DEFINE([HAVE_MATEPANELAPPLET], [1], [Define if you have libmatepanelapplet]) + enable_mate_applet=yes + ], + [if test "x$enable_mate_applet" = xyes; then + AC_MSG_FAILURE([--enable-mate-applet was given, but test for libmatepanelapplet failed]) + fi] + )])]) AM_CONDITIONAL([WANT_MATE_APPLET], [test x$enable_mate_applet = xyes]) diff --git a/libtopmenu-client/Makefile.am b/libtopmenu-client/Makefile.am index b57343b..f4f8b6f 100644 --- a/libtopmenu-client/Makefile.am +++ b/libtopmenu-client/Makefile.am @@ -1,8 +1,21 @@ -lib_LTLIBRARIES = libtopmenu-client.la -libtopmenu_client_la_SOURCES = topmenu-client.c topmenu-client.h \ +if GTK3 + +lib_LTLIBRARIES = libtopmenu-client-gtk3.la +libtopmenu_client_gtk3_la_SOURCES = topmenu-client.c topmenu-client.h \ + topmenu-monitor.c topmenu-monitor.h \ + topmenu-appmenubar.c topmenu-appmenubar.h +libtopmenu_client_gtk3_la_CPPFLAGS = $(GTK_CFLAGS) -DG_LOG_DOMAIN=\"topmenu-client\" +libtopmenu_client_gtk3_la_LIBADD = $(GTK_LIBS) + +else + +lib_LTLIBRARIES = libtopmenu-client-gtk2.la +libtopmenu_client_gtk2_la_SOURCES = topmenu-client.c topmenu-client.h \ topmenu-monitor.c topmenu-monitor.h \ topmenu-appmenubar.c topmenu-appmenubar.h -libtopmenu_client_la_CPPFLAGS = $(GTK_CFLAGS) -DG_LOG_DOMAIN=\"topmenu-client\" -libtopmenu_client_la_LIBADD = $(GTK_LIBS) +libtopmenu_client_gtk2_la_CPPFLAGS = $(GTK_CFLAGS) -DG_LOG_DOMAIN=\"topmenu-client\" +libtopmenu_client_gtk2_la_LIBADD = $(GTK_LIBS) + +endif include_HEADERS = topmenu-client.h topmenu-monitor.h topmenu-appmenubar.h diff --git a/libtopmenu-client/topmenu-appmenubar.c b/libtopmenu-client/topmenu-appmenubar.c index 7d94cf5..5c66d91 100644 --- a/libtopmenu-client/topmenu-appmenubar.c +++ b/libtopmenu-client/topmenu-appmenubar.c @@ -48,6 +48,7 @@ static void topmenu_app_menu_bar_class_init(TopMenuAppMenuBarClass *klass) g_object_class_install_properties(obj_class, N_PROPERTIES, properties); +#if GTK_MAJOR_VERSION == 2 gtk_rc_parse_string ( "style \"app-menubar-style\"\n" "{\n" @@ -55,10 +56,41 @@ static void topmenu_app_menu_bar_class_init(TopMenuAppMenuBarClass *klass) " GtkMenuBar::internal-padding = 0\n" "}\n" "class \"TopMenuAppMenuBar\" style \"app-menubar-style\""); +#endif } static void topmenu_app_menu_bar_init(TopMenuAppMenuBar *self) { +#if GTK_MAJOR_VERSION == 3 + GError *error = NULL; + GtkCssProvider *provider = gtk_css_provider_new(); + GtkStyleContext *style_context = gtk_widget_get_style_context(GTK_WIDGET(self)); + static const char *css = + "TopMenuAppMenuBar {\n" + " box-shadow: none;\n" + " padding: 0;\n" + " background-color: @os_chrome_bg_color;\n" + " background-image: none;\n" + " color: @os_chrome_fg_color;\n" + "}\n" + "\n" + "TopMenuAppMenuBar .menu .menuitem *:active {\n" + " color: @theme_text_color;\n" + "}\n" + "\n" + "TopMenuAppMenuBar .menu .menuitem *:selected {\n" + " color: @theme_selected_fg_color;\n" + "}\n"; + if (gtk_css_provider_load_from_data(provider, css, -1, &error)) { + gtk_style_context_add_provider(style_context, + GTK_STYLE_PROVIDER(provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } else { + g_warning("Error while loading CSS: %s", error->message); + g_error_free(error); + } +#endif + self->app_menu_item = GTK_MENU_ITEM(gtk_menu_item_new_with_label(g_get_application_name())); GtkLabel *app_label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(self->app_menu_item))); PangoAttrList *app_label_attr = pango_attr_list_new(); diff --git a/libtopmenu-client/topmenu-client.c b/libtopmenu-client/topmenu-client.c index f7d3e58..cbc2d20 100644 --- a/libtopmenu-client/topmenu-client.c +++ b/libtopmenu-client/topmenu-client.c @@ -43,7 +43,7 @@ static gboolean handle_widget_button_event(GtkWidget *widget, GdkEvent *event, G e.type = event->type == GDK_BUTTON_PRESS ? ButtonPress : ButtonRelease; e.xbutton.window = xwin; e.xbutton.display = dpy; - e.xbutton.root = GDK_WINDOW_XWINDOW(root); + e.xbutton.root = gdk_x11_window_get_xid(root); e.xbutton.time = event->button.time; e.xbutton.button = event->button.button; e.xbutton.state = event->button.state; @@ -76,7 +76,7 @@ void topmenu_client_connect_window_widget(GdkWindow *window, GtkWidget *widget) topmenu_client_disconnect_window(window); } - Window xwin = GDK_WINDOW_XID(window); + Window xwin = gdk_x11_window_get_xid(window); GtkPlug *plug = GTK_PLUG(gtk_plug_new(0)); gtk_container_add(GTK_CONTAINER(plug), widget); g_signal_connect_object(plug, "delete-event", @@ -110,7 +110,7 @@ void topmenu_client_disconnect_window(GdkWindow *window) gpointer window_data = g_object_steal_data(G_OBJECT(window), OBJECT_DATA_KEY_PLUG); g_return_if_fail(window_data); - Window xwin = GDK_WINDOW_XID(window); + Window xwin = gdk_x11_window_get_xid(window); GtkPlug *plug = GTK_PLUG(window_data); g_return_if_fail(plug); diff --git a/libtopmenu-client/topmenu-monitor.c b/libtopmenu-client/topmenu-monitor.c index 2f63e9b..94302ef 100644 --- a/libtopmenu-client/topmenu-monitor.c +++ b/libtopmenu-client/topmenu-monitor.c @@ -110,7 +110,7 @@ static void topmenu_monitor_dispose(GObject *obj) if (self->priv->cur_server) { gdk_window_remove_filter(self->priv->cur_server, handle_cur_server_event, self); - gdk_window_unref(self->priv->cur_server); + g_object_unref(self->priv->cur_server); self->priv->cur_server = 0; } self->priv->selection = NULL; diff --git a/libtopmenu-server/Makefile.am b/libtopmenu-server/Makefile.am index 8a17f5f..98de595 100644 --- a/libtopmenu-server/Makefile.am +++ b/libtopmenu-server/Makefile.am @@ -1,7 +1,18 @@ -lib_LTLIBRARIES = libtopmenu-server.la -libtopmenu_server_la_SOURCES = topmenu-server.c topmenu-server.h topmenu-widget.c topmenu-widget.h -libtopmenu_server_la_CPPFLAGS = $(GTK_CFLAGS) $(WNCK_CFLAGS) $(MATEWNCK_CFLAGS) -DG_LOG_DOMAIN=\"topmenu-server\" -libtopmenu_server_la_LIBADD = $(GTK_LIBS) $(WNCK_LIBS) $(MATEWNCK_LIBS) +if GTK3 + +lib_LTLIBRARIES = libtopmenu-server-gtk3.la +libtopmenu_server_gtk3_la_SOURCES = topmenu-server.c topmenu-server.h topmenu-widget.c topmenu-widget.h +libtopmenu_server_gtk3_la_CPPFLAGS = $(GTK_CFLAGS) $(WNCK_CFLAGS) $(MATEWNCK_CFLAGS) -DG_LOG_DOMAIN=\"topmenu-server\" +libtopmenu_server_gtk3_la_LIBADD = $(GTK_LIBS) $(WNCK_LIBS) $(MATEWNCK_LIBS) + +else + +lib_LTLIBRARIES = libtopmenu-server-gtk2.la +libtopmenu_server_gtk2_la_SOURCES = topmenu-server.c topmenu-server.h topmenu-widget.c topmenu-widget.h +libtopmenu_server_gtk2_la_CPPFLAGS = $(GTK_CFLAGS) $(WNCK_CFLAGS) $(MATEWNCK_CFLAGS) -DG_LOG_DOMAIN=\"topmenu-server\" +libtopmenu_server_gtk2_la_LIBADD = $(GTK_LIBS) $(WNCK_LIBS) $(MATEWNCK_LIBS) + +endif include_HEADERS = topmenu-server.h topmenu-widget.h diff --git a/libtopmenu-server/topmenu-widget.c b/libtopmenu-server/topmenu-widget.c index 8121fc5..e4c51de 100644 --- a/libtopmenu-server/topmenu-widget.c +++ b/libtopmenu-server/topmenu-widget.c @@ -123,7 +123,7 @@ static void topmenu_widget_embed_topmenu_window(TopMenuWidget *self, Window wind GdkWindow *cur = gtk_socket_get_plug_window(self->socket); if (cur) { - if (gdk_x11_window_get_xid(cur) == window) { + if (GDK_WINDOW_XID(cur) == window) { // Trying to embed the same client again return; // Nothing to do } diff --git a/libtopmenu-server/topmenu-widget.h b/libtopmenu-server/topmenu-widget.h index 19d9784..1634bcc 100644 --- a/libtopmenu-server/topmenu-widget.h +++ b/libtopmenu-server/topmenu-widget.h @@ -3,7 +3,7 @@ #include -#if GTK_VERSION == 3 +#if GTK_MAJOR_VERSION == 3 #include #endif diff --git a/module/Makefile.am b/module/Makefile.am index ac75b74..169d304 100644 --- a/module/Makefile.am +++ b/module/Makefile.am @@ -5,5 +5,5 @@ gtk_module_LTLIBRARIES = libtopmenu-gtk-module.la libtopmenu_gtk_module_la_SOURCES = main.c data.c data.h \ menuitem-proxy.c menuitem-proxy.h appmenu.c appmenu.h libtopmenu_gtk_module_la_CPPFLAGS = $(GTK_CFLAGS) -DG_LOG_DOMAIN=\"topmenu-module\" -libtopmenu_gtk_module_la_LIBADD = $(GTK_LIBS) ../libtopmenu-client/libtopmenu-client.la +libtopmenu_gtk_module_la_LIBADD = $(GTK_LIBS) ../libtopmenu-client/libtopmenu-client-gtk$(GTK_VERSION).la libtopmenu_gtk_module_la_LDFLAGS = -avoid-version -module -shared diff --git a/module/data.c b/module/data.c index 9225d01..7af7e81 100644 --- a/module/data.c +++ b/module/data.c @@ -1,3 +1,11 @@ +#include + +#include "../global.h" + +#if GTK_MAJOR_VERSION == 3 +#include +#endif + #include "../libtopmenu-client/topmenu-monitor.h" #include "data.h" diff --git a/module/main.c b/module/main.c index 42ea332..3672fd5 100644 --- a/module/main.c +++ b/module/main.c @@ -441,7 +441,7 @@ hijacked_application_window_realize (GtkWidget *widget) if (pre_hijacked_application_window_realize != NULL) (* pre_hijacked_application_window_realize) (widget); - gtk_window_get_window_data (GTK_WINDOW (widget)); + topmenu_get_window_data (GTK_WINDOW (widget)); } #endif @@ -536,7 +536,7 @@ hijacked_menu_bar_get_preferred_width (GtkWidget *widget, if (pre_hijacked_menu_bar_get_preferred_width != NULL) (* pre_hijacked_menu_bar_get_preferred_width) (widget, minimum_width, natural_width); - if (gtk_widget_shell_shows_menubar (widget)) + if (topmenu_should_hide_menubar(widget)) { *minimum_width = 0; *natural_width = 0; @@ -553,7 +553,7 @@ hijacked_menu_bar_get_preferred_height (GtkWidget *widget, if (pre_hijacked_menu_bar_get_preferred_height != NULL) (* pre_hijacked_menu_bar_get_preferred_height) (widget, minimum_height, natural_height); - if (gtk_widget_shell_shows_menubar (widget)) + if (topmenu_should_hide_menubar(widget)) { *minimum_height = 0; *natural_height = 0; @@ -571,7 +571,7 @@ hijacked_menu_bar_get_preferred_width_for_height (GtkWidget *widget, if (pre_hijacked_menu_bar_get_preferred_width_for_height != NULL) (* pre_hijacked_menu_bar_get_preferred_width_for_height) (widget, height, minimum_width, natural_width); - if (gtk_widget_shell_shows_menubar (widget)) + if (topmenu_should_hide_menubar(widget)) { *minimum_width = 0; *natural_width = 0; @@ -589,7 +589,7 @@ hijacked_menu_bar_get_preferred_height_for_width (GtkWidget *widget, if (pre_hijacked_menu_bar_get_preferred_height_for_width != NULL) (* pre_hijacked_menu_bar_get_preferred_height_for_width) (widget, width, minimum_height, natural_height); - if (gtk_widget_shell_shows_menubar (widget)) + if (topmenu_should_hide_menubar(widget)) { *minimum_height = 0; *natural_height = 0; diff --git a/module/menuitem-proxy.c b/module/menuitem-proxy.c index 6a3e555..fbab6f1 100644 --- a/module/menuitem-proxy.c +++ b/module/menuitem-proxy.c @@ -39,6 +39,152 @@ static void init_static_data() } } +#if GTK_MAJOR_VERSION == 3 +/* What could possibly go wrong? */ +typedef enum +{ + GTK_DIRECTION_LEFT, + GTK_DIRECTION_RIGHT +} GtkSubmenuDirection; + +typedef enum +{ + GTK_TOP_BOTTOM, + GTK_LEFT_RIGHT +} GtkSubmenuPlacement; + +struct _GtkMenuPrivate +{ + GtkWidget *parent_menu_item; + GtkWidget *old_active_menu_item; + + GtkAccelGroup *accel_group; + gchar *accel_path; + + GtkMenuPositionFunc position_func; + gpointer position_func_data; + GDestroyNotify position_func_data_destroy; + gint position_x; + gint position_y; + + guint toggle_size; + guint accel_size; + + GtkWidget *toplevel; + + GtkWidget *tearoff_window; + GtkWidget *tearoff_hbox; + GtkWidget *tearoff_scrollbar; + GtkAdjustment *tearoff_adjustment; + + GdkWindow *view_window; + GdkWindow *bin_window; + + gint scroll_offset; + gint saved_scroll_offset; + gint scroll_step; + + guint scroll_timeout; + + guint needs_destruction_ref : 1; + guint torn_off : 1; + /* The tearoff is active when it is torn off and the not-torn-off + * menu is not popped up. + */ + guint tearoff_active : 1; + guint scroll_fast : 1; + + guint upper_arrow_visible : 1; + guint lower_arrow_visible : 1; + guint upper_arrow_prelight : 1; + guint lower_arrow_prelight : 1; + + guint have_position : 1; + guint have_layout : 1; + guint seen_item_enter : 1; + guint ignore_button_release : 1; + guint no_toggle_size : 1; + guint drag_already_pressed : 1; + guint drag_scroll_started : 1; + + /* info used for the table */ + guint *heights; + gint heights_length; + gint requested_height; + + gboolean initially_pushed_in; + gint monitor_num; + + /* Cached layout information */ + gint n_rows; + gint n_columns; + + gchar *title; + + /* Arrow states */ + GtkStateFlags lower_arrow_state; + GtkStateFlags upper_arrow_state; + + /* navigation region */ + gint navigation_x; + gint navigation_y; + gint navigation_width; + gint navigation_height; + + guint navigation_timeout; + + gdouble drag_start_y; + gint initial_drag_offset; +}; + +struct _GtkMenuShellPrivate +{ + GList *children; + + GtkWidget *active_menu_item; + GtkWidget *parent_menu_shell; + void *tracker; + + guint button; + guint32 activate_time; + + guint active : 1; + guint have_grab : 1; + guint have_xgrab : 1; + guint ignore_enter : 1; + guint keyboard_mode : 1; + + guint take_focus : 1; + guint activated_submenu : 1; + guint in_unselectable_item : 1; +}; + +struct _GtkMenuItemPrivate +{ + GtkWidget *submenu; + GdkWindow *event_window; + + guint16 toggle_size; + guint16 accelerator_width; + + guint timer; + + gchar *accel_path; + + GtkAction *action; + void *action_helper; + + guint show_submenu_indicator : 1; + guint submenu_placement : 1; + guint submenu_direction : 1; + guint right_justify : 1; + guint timer_from_keypress : 1; + guint from_menubar : 1; + guint use_action_appearance : 1; + guint reserve_indicator : 1; +}; +#endif + static void free_timeval (GTimeVal *val) { @@ -50,6 +196,23 @@ get_offsets (GtkMenu *menu, gint *horizontal_offset, gint *vertical_offset) { +#if GTK_MAJOR_VERSION == 3 + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder padding; + + gtk_widget_style_get (GTK_WIDGET (menu), + "horizontal-offset", horizontal_offset, + "vertical-offset", vertical_offset, + NULL); + + context = gtk_widget_get_style_context (GTK_WIDGET (menu)); + state = gtk_widget_get_state_flags (GTK_WIDGET (menu)); + gtk_style_context_get_padding (context, state, &padding); + + *vertical_offset -= padding.top; + *horizontal_offset += padding.left; +#else gint vertical_padding; gint horizontal_padding; @@ -63,6 +226,7 @@ get_offsets (GtkMenu *menu, *vertical_offset -= GTK_WIDGET (menu)->style->ythickness; *vertical_offset -= vertical_padding; *horizontal_offset += horizontal_padding; +#endif } static void @@ -72,6 +236,153 @@ menu_item_position_menu (GtkMenu *menu, gboolean *push_in, gpointer user_data) { +#if GTK_MAJOR_VERSION == 3 + GtkMenuItem *menu_item = GTK_MENU_ITEM (user_data); + GtkMenuItemPrivate *priv = menu_item->priv; + GtkAllocation allocation; + GtkWidget *widget; + GtkMenuItem *parent_menu_item; + GtkWidget *parent; + GdkScreen *screen; + gint twidth, theight; + gint tx, ty; + GtkTextDirection direction; + GdkRectangle monitor; + gint monitor_num; + gint horizontal_offset; + gint vertical_offset; + gint available_left, available_right; + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder parent_padding; + + g_return_if_fail (menu != NULL); + g_return_if_fail (x != NULL); + g_return_if_fail (y != NULL); + + widget = GTK_WIDGET (user_data); + + if (push_in) + *push_in = FALSE; + + direction = gtk_widget_get_direction (widget); + + twidth = gtk_widget_get_allocated_width (GTK_WIDGET (menu)); + theight = gtk_widget_get_allocated_height (GTK_WIDGET (menu)); + + screen = gtk_widget_get_screen (GTK_WIDGET (menu)); + monitor_num = gdk_screen_get_monitor_at_window (screen, priv->event_window); + if (monitor_num < 0) + monitor_num = 0; + gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor); + + if (!gdk_window_get_origin (gtk_widget_get_window (widget), &tx, &ty)) + { + g_warning ("Menu not on screen"); + return; + } + + gtk_widget_get_allocation (widget, &allocation); + + tx += allocation.x; + ty += allocation.y; + + get_offsets (menu, &horizontal_offset, &vertical_offset); + + available_left = tx - monitor.x; + available_right = monitor.x + monitor.width - (tx + allocation.width); + + parent = gtk_widget_get_parent (widget); + priv->from_menubar = GTK_IS_MENU_BAR (parent); + + switch (priv->submenu_placement) + { + case GTK_TOP_BOTTOM: + if (direction == GTK_TEXT_DIR_LTR) + priv->submenu_direction = GTK_DIRECTION_RIGHT; + else + { + priv->submenu_direction = GTK_DIRECTION_LEFT; + tx += allocation.width - twidth; + } + if ((ty + allocation.height + theight) <= monitor.y + monitor.height) + ty += allocation.height; + else if ((ty - theight) >= monitor.y) + ty -= theight; + else if (monitor.y + monitor.height - (ty + allocation.height) > ty) + ty += allocation.height; + else + ty -= theight; + break; + + case GTK_LEFT_RIGHT: + if (GTK_IS_MENU (parent)) + parent_menu_item = GTK_MENU_ITEM (GTK_MENU (parent)->priv->parent_menu_item); + else + parent_menu_item = NULL; + + context = gtk_widget_get_style_context (parent); + state = gtk_widget_get_state_flags (parent); + gtk_style_context_get_padding (context, state, &parent_padding); + + if (parent_menu_item && !GTK_MENU (parent)->priv->torn_off) + { + priv->submenu_direction = parent_menu_item->priv->submenu_direction; + } + else + { + if (direction == GTK_TEXT_DIR_LTR) + priv->submenu_direction = GTK_DIRECTION_RIGHT; + else + priv->submenu_direction = GTK_DIRECTION_LEFT; + } + + switch (priv->submenu_direction) + { + case GTK_DIRECTION_LEFT: + if (tx - twidth - parent_padding.left - horizontal_offset >= monitor.x || + available_left >= available_right) + tx -= twidth + parent_padding.left + horizontal_offset; + else + { + priv->submenu_direction = GTK_DIRECTION_RIGHT; + tx += allocation.width + parent_padding.right + horizontal_offset; + } + break; + + case GTK_DIRECTION_RIGHT: + if (tx + allocation.width + parent_padding.right + horizontal_offset + twidth <= monitor.x + monitor.width || + available_right >= available_left) + tx += allocation.width + parent_padding.right + horizontal_offset; + else + { + priv->submenu_direction = GTK_DIRECTION_LEFT; + tx -= twidth + parent_padding.left + horizontal_offset; + } + break; + } + + ty += vertical_offset; + + /* If the height of the menu doesn't fit we move it upward. */ + ty = CLAMP (ty, monitor.y, MAX (monitor.y, monitor.y + monitor.height - theight)); + break; + } + + /* If we have negative, tx, here it is because we can't get + * the menu all the way on screen. Favor the left portion. + */ + *x = CLAMP (tx, monitor.x, MAX (monitor.x, monitor.x + monitor.width - twidth)); + *y = ty; + + gtk_menu_set_monitor (menu, monitor_num); + + if (!gtk_widget_get_visible (menu->priv->toplevel)) + { + gtk_window_set_type_hint (GTK_WINDOW (menu->priv->toplevel), priv->from_menubar? + GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU : GDK_WINDOW_TYPE_HINT_POPUP_MENU); + } +#else GtkMenuItem *menu_item; GtkWidget *widget; GtkMenuItem *parent_menu_item; @@ -222,6 +533,7 @@ menu_item_position_menu (GtkMenu *menu, gtk_window_set_type_hint (GTK_WINDOW (menu->toplevel), menu_item->from_menubar? GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU : GDK_WINDOW_TYPE_HINT_POPUP_MENU); } +#endif } static void handle_menuitem_notify(GtkMenuItem *item, GParamSpec *pspec, GtkMenuItem *proxy) @@ -251,7 +563,7 @@ static gboolean handle_menuitem_mnemonic_activate(GtkMenuItem *item, gboolean cy if (parent && monitor->available) { GtkMenuShell *parent_shell = GTK_MENU_SHELL(parent); - if (GTK_IS_MENU_BAR(parent_shell) || parent_shell->active) { + if (GTK_IS_MENU_BAR(parent_shell) || parent_shell->priv->active) { gtk_widget_mnemonic_activate(GTK_WIDGET(proxy), cycling); return TRUE; } @@ -278,12 +590,13 @@ static void handle_parent_move_current(GtkMenuShell *shell, GtkMenuDirectionType static void handle_proxy_select(GtkMenuItem *proxy, GtkMenuItem *item) { GtkWidget *submenu = gtk_menu_item_get_submenu(item); + GtkWidget *parent = gtk_widget_get_parent(GTK_WIDGET(proxy)); - if (submenu) { + if (submenu && parent) { if (!gtk_widget_is_sensitive(GTK_WIDGET(submenu))) return; - GtkMenuShell *parent_shell = GTK_MENU_SHELL(GTK_WIDGET(proxy)->parent); + GtkMenuShell *parent_shell = GTK_MENU_SHELL(parent); GTimeVal *popup_time = g_slice_new0(GTimeVal); g_get_current_time(popup_time); @@ -302,7 +615,7 @@ static void handle_proxy_select(GtkMenuItem *proxy, GtkMenuItem *item) GTK_WIDGET(proxy), menu_item_position_menu, proxy, - parent_shell->button, + parent_shell->priv->button, 0); } } @@ -337,11 +650,8 @@ static void handle_proxy_activate_item(GtkMenuItem *proxy, GtkMenuItem *item) if (submenu) { GtkMenuShell *parent = GTK_MENU_SHELL(gtk_widget_get_parent(GTK_WIDGET(proxy))); if (parent) { - if (!parent->active) { - //gtk_grab_add(GTK_WIDGET(parent)); - //parent->have_grab = TRUE; - parent->active = TRUE; - } + parent->priv->active = TRUE; + // We do not add grabs here, like Gtk+ does, because they are already done. gtk_menu_shell_select_item(parent, GTK_WIDGET(proxy)); gtk_menu_shell_select_first(GTK_MENU_SHELL(submenu), TRUE); } @@ -358,9 +668,9 @@ static GtkWidget *construct_image_widget_proxy(GtkImage *widget) gtk_image_get_stock(widget, &icon_name, &icon_size); return gtk_image_new_from_stock(icon_name, icon_size); case GTK_IMAGE_EMPTY: - return gtk_image_new(); + return NULL; default: - return gtk_image_new(); + return NULL; } } @@ -382,15 +692,15 @@ GtkMenuItem *topmenu_create_proxy_menu_item(GtkMenuItem *item) if (iwidget) { // Let's suppport some common widget types if (GTK_IS_IMAGE(iwidget)) { + GtkImage *iwidgetimg = GTK_IMAGE(iwidget); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(proxy), - construct_image_widget_proxy(GTK_IMAGE(iwidget))); + construct_image_widget_proxy(iwidgetimg)); } } } gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(proxy), gtk_image_menu_item_get_always_show_image(iitem)); - } - else if (GTK_IS_SEPARATOR_MENU_ITEM(item)) { + } else if (GTK_IS_SEPARATOR_MENU_ITEM(item)) { proxy = GTK_MENU_ITEM(gtk_separator_menu_item_new()); } else { proxy = GTK_MENU_ITEM(gtk_menu_item_new_with_mnemonic(label)); diff --git a/test/Makefile.am b/test/Makefile.am index 4455221..5a06736 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -5,8 +5,8 @@ AM_LDFLAGS = $(GTK_LIBS) client_SOURCES = client.c client_CPPFLAGS = $(GTK_CFLAGS) -client_LDADD = $(GTK_LIBS) ../libtopmenu-client/libtopmenu-client.la +client_LDADD = $(GTK_LIBS) ../libtopmenu-client/libtopmenu-client-gtk$(GTK_VERSION).la server_SOURCES = server.c server_CPPFLAGS = $(GTK_CFLAGS) -server_LDADD = $(GTK_LIBS) ../libtopmenu-server/libtopmenu-server.la +server_LDADD = $(GTK_LIBS) ../libtopmenu-server/libtopmenu-server-gtk$(GTK_VERSION).la diff --git a/test/client.c b/test/client.c index 08312e6..8aff036 100644 --- a/test/client.c +++ b/test/client.c @@ -19,25 +19,27 @@ static GtkWidget * create_menu_bar(void) GtkLabel *app_label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(app))); gtk_label_set_markup(app_label, "Client"); - gtk_menu_bar_append(bar, GTK_WIDGET(app)); - gtk_menu_bar_append(bar, GTK_WIDGET(file)); - gtk_menu_bar_append(bar, GTK_WIDGET(edit)); - gtk_menu_bar_append(bar, GTK_WIDGET(help)); + gtk_menu_shell_append(GTK_MENU_SHELL(bar), GTK_WIDGET(app)); + gtk_menu_shell_append(GTK_MENU_SHELL(bar), GTK_WIDGET(file)); + gtk_menu_shell_append(GTK_MENU_SHELL(bar), GTK_WIDGET(edit)); + gtk_menu_shell_append(GTK_MENU_SHELL(bar), GTK_WIDGET(help)); GtkMenu *app_menu = GTK_MENU(gtk_menu_new()); GtkMenuItem *quit = GTK_MENU_ITEM(gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL)); - gtk_menu_append(app_menu, GTK_WIDGET(quit)); + gtk_menu_shell_append(GTK_MENU_SHELL(app_menu), GTK_WIDGET(quit)); gtk_menu_item_set_submenu(app, GTK_WIDGET(app_menu)); GtkMenu *file_menu = GTK_MENU(gtk_menu_new()); GtkMenuItem *new = GTK_MENU_ITEM(gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL)); - gtk_menu_append(file_menu, GTK_WIDGET(new)); + gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), GTK_WIDGET(new)); GtkMenuItem *open = GTK_MENU_ITEM(gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL)); - gtk_menu_append(file_menu, GTK_WIDGET(open)); + gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), GTK_WIDGET(open)); GtkMenuItem *close = GTK_MENU_ITEM(gtk_image_menu_item_new_from_stock(GTK_STOCK_CLOSE, NULL)); - gtk_menu_append(file_menu, GTK_WIDGET(close)); + gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), GTK_WIDGET(close)); gtk_menu_item_set_submenu(file, GTK_WIDGET(file_menu)); + gtk_widget_show_all(GTK_WIDGET(bar)); + return GTK_WIDGET(bar); } @@ -58,18 +60,18 @@ GtkWindow * create_main_window() int main(int argc, char **argv) { - gtk_set_locale(); gtk_init(&argc, &argv); mainwin = create_main_window(); - topmenu_monitor_get_instance(); g_signal_connect(mainwin, "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_realize(GTK_WIDGET(mainwin)); +#if 0 topmenu_client_connect_window_widget(gtk_widget_get_window(GTK_WIDGET(mainwin)), create_menu_bar()); +#endif gtk_widget_show_all(GTK_WIDGET(mainwin)); diff --git a/test/server.c b/test/server.c index d0b9135..031ce61 100644 --- a/test/server.c +++ b/test/server.c @@ -22,7 +22,6 @@ static void construct_main_window() int main(int argc, char **argv) { - gtk_set_locale(); gtk_init(&argc, &argv); construct_main_window(); -- cgit v1.2.3