00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "config.h"
00032
00033
00034 #include <gtk/gtk.h>
00035 #include <gdk/gdkkeysyms.h>
00036 #include <string.h>
00037
00038
00039 #include <libergtk/ergtk.h>
00040 #include <liberutils/display_utils.h>
00041
00042
00043 #include "log.h"
00044 #include "i18n.h"
00045 #include "ipc.h"
00046 #include "menustore.h"
00047 #include "pixlist.h"
00048 #include "popup.h"
00049
00050
00051
00052
00053
00054 const gint MENU_OFFSET_LEFT = 12;
00055 const gint MENU_OFFSET_BOTTOM = 45;
00056
00057
00058
00059
00060
00061
00062 static GtkWidget *g_menu = NULL;
00063 static gboolean is_active = FALSE;
00064 static gboolean g_dont_show = FALSE;
00065
00066
00067
00068
00069
00070
00071 #if (TIMING_ON)
00072 #include <stdlib.h>
00073 #include <time.h>
00074 static u_int64_t get_time_now()
00075 {
00076 struct timespec now;
00077 clock_gettime(CLOCK_MONOTONIC, &now);
00078 u_int64_t now64 = now.tv_sec;
00079 now64 *= 1000000;
00080 now64 += (now.tv_nsec/1000);
00081 return now64;
00082 }
00083
00084 static u_int64_t t1 = 0;
00085 static u_int64_t t2 = 0;
00086
00087 static void start_timer()
00088 {
00089 LOGPRINTF("");
00090 if (t1 == 0) t1 = get_time_now();
00091 }
00092
00093
00094 static void stop_timer(const char* text)
00095 {
00096 if (t1 != 0) {
00097 t2 = get_time_now();
00098 float duration = t2 - t1;
00099 printf("%s DURATION = %4.1lf ms\n\n", text, duration / 1000);
00100 t1 = 0;
00101 }
00102 }
00103 #endif
00104
00105 static void set_active (gboolean do_active);
00106 static void idle_update_display (gint type);
00107
00108
00109
00110
00111
00112
00113
00114 gboolean popup_set_popup_show(const char* statestr)
00115 {
00116 gboolean last_active = is_active;
00117
00118 if (g_dont_show)
00119 {
00120 return FALSE;
00121 }
00122
00123 if (g_ascii_strcasecmp(statestr, "show") == 0)
00124 {
00125 set_active(TRUE);
00126 }
00127 else if (g_ascii_strcasecmp(statestr, "hide") == 0)
00128 {
00129 set_active(FALSE);
00130 }
00131 else if (g_ascii_strcasecmp(statestr, "toggle") == 0)
00132 {
00133 set_active(!is_active);
00134 }
00135 else if (g_ascii_strcasecmp(statestr, "block") == 0)
00136 {
00137
00138 set_active(FALSE);
00139 ipc_set_enabled(FALSE);
00140 }
00141 else if (g_ascii_strcasecmp(statestr, "unblock") == 0)
00142 {
00143 set_active(FALSE);
00144 ipc_set_enabled(TRUE);
00145 }
00146 else
00147 {
00148 ERRORPRINTF("state unknown: %s", statestr);
00149 }
00150
00151 return (last_active != is_active);
00152 }
00153
00154
00155 void popup_set_popup_block(gboolean block)
00156 {
00157 g_dont_show = block;
00158 }
00159
00160
00161 gboolean popup_get_popup_block()
00162 {
00163 return g_dont_show;
00164 }
00165
00166
00167 static void set_menuitem_markup(GtkWidget* widget, const char* text, int state)
00168 {
00169 LOGPRINTF("text='%s' state=%d", text, state);
00170 GtkWidget *itemlabel = gtk_bin_get_child(GTK_BIN(widget));
00171
00172
00173 gchar *markup = NULL;
00174 if (state == MENU_STATE_SELECTED) {
00175 markup = g_markup_printf_escaped("<span weight=\"bold\">%s</span>", text);
00176 }
00177 else
00178 {
00179 markup = g_markup_escape_text(text, -1);
00180 }
00181 gtk_label_set_markup(GTK_LABEL(itemlabel), markup);
00182 g_free(markup);
00183
00184
00185 if (state == MENU_STATE_DISABLED || text[0] == 0)
00186 {
00187 #if MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00188 if (text[0] != 0) {
00189 gtk_widget_set_sensitive(widget, FALSE);
00190 gtk_widget_show(widget);
00191 } else {
00192 gtk_widget_hide(widget);
00193
00194 }
00195 #else
00196 gtk_widget_hide(widget);
00197 #endif
00198 }
00199 else
00200 {
00201 gtk_widget_show(widget);
00202 }
00203 }
00204
00205
00206
00207
00208
00209
00210 static void on_menu_deactivate(GtkMenuShell *menu, gpointer user_data)
00211 {
00212 set_active(FALSE);
00213 }
00214
00215
00216 static gboolean on_menu_key_press(GtkMenuShell *menu, GdkEventKey *event, gpointer user_data)
00217 {
00218 LOGPRINTF("entry: type [%d] keyval [%d]", event->type, event->keyval);
00219
00220 if (event && (event->type == GDK_KEY_PRESS))
00221 {
00222 switch (event->keyval)
00223 {
00224 case GDK_F1:
00225 set_active(FALSE);
00226 break;
00227 case GDK_F10:
00228 ipc_sys_standby();
00229 break;
00230 default:
00231 break;
00232 }
00233 }
00234 return FALSE;
00235 }
00236
00237
00238 static void on_item_back_activate(GtkMenuItem *item, gpointer user_data)
00239 {
00240 GtkWidget *menu_shell = GTK_WIDGET(user_data);
00241
00242
00243 g_signal_emit_by_name(menu_shell, "move-current", GTK_MENU_DIR_PARENT, NULL);
00244 }
00245
00246
00247 static void on_item_activate(GtkMenuItem *item, gpointer menu_data)
00248 {
00249 gboolean ok = menustore_activate_item_iter(menu_data, ipc_send_item_activated);
00250 if (ok) set_active(FALSE);
00251 }
00252
00253
00254 static void on_menu_move_scroll(GtkMenu *menu,
00255 GtkScrollType arg1,
00256 gpointer user_data)
00257 {
00258 display_gain_control();
00259 idle_update_display(DM_HINT_CURSOR);
00260 }
00261
00262
00263 static gboolean on_menu_move_selected(GtkMenuShell *menu_shell,
00264 gint distance,
00265 gpointer user_data)
00266 {
00267 display_gain_control();
00268 idle_update_display(DM_HINT_CURSOR);
00269 return FALSE;
00270 }
00271
00272
00273 static void menu_set_position(GtkMenu *menu,
00274 gint *x,
00275 gint *y,
00276 gboolean *push_in,
00277 gpointer user_data)
00278 {
00279 g_assert(g_menu);
00280 if (menu == GTK_MENU(g_menu))
00281 {
00282 gint w, h;
00283 GtkRequisition req;
00284
00285 gdk_window_get_geometry(gdk_get_default_root_window(), NULL, NULL, &w, &h, NULL);
00286 gtk_widget_size_request(g_menu, &req);
00287
00288 *x = MENU_OFFSET_LEFT;
00289 *y = h - MENU_OFFSET_BOTTOM - req.height;
00290
00291 }
00292 }
00293
00294
00295 static GtkWidget *create_item(const gchar *text, GdkPixbuf *img)
00296 {
00297 GtkWidget *widget = gtk_image_menu_item_new_with_label(text);
00298 GtkWidget *item_image = gtk_image_new_from_pixbuf(img);
00299 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget),item_image);
00300 gtk_widget_show(item_image);
00301 gtk_widget_show(widget);
00302
00303 return widget;
00304 }
00305
00306
00307 static gpointer add_popup_item(const char* name,
00308 const char* text,
00309 enum menu_state state,
00310 GdkPixbuf *img,
00311 gpointer menu_data,
00312 gpointer user_data)
00313 {
00314 GtkWidget *widget = create_item(text, img);
00315 set_menuitem_markup(widget, text, state);
00316
00317
00318 gtk_menu_shell_append(GTK_MENU_SHELL(user_data), widget);
00319
00320 g_signal_connect(G_OBJECT(widget), "activate", G_CALLBACK(on_item_activate), menu_data);
00321 return widget;
00322 }
00323
00324
00325 static gpointer add_popup_submenu(const char* name,
00326 const char* text,
00327 enum menu_state state,
00328 GdkPixbuf *img,
00329 gpointer menu_data,
00330 gpointer user_data)
00331 {
00332 GtkWidget* widget = add_popup_item(name, text, state, img, menu_data, user_data);
00333
00334
00335 GtkWidget *submenu = gtk_menu_new();
00336 gtk_signal_connect(GTK_OBJECT(submenu), "key-press-event", GTK_SIGNAL_FUNC(on_menu_key_press), NULL);
00337 g_signal_connect(G_OBJECT(submenu), "move-scroll", G_CALLBACK(on_menu_move_scroll), NULL);
00338 g_signal_connect(G_OBJECT(submenu), "move-selected", G_CALLBACK(on_menu_move_selected), NULL);
00339 g_signal_connect(G_OBJECT(submenu), "deactivate", G_CALLBACK(on_menu_deactivate), NULL);
00340 gtk_menu_item_set_submenu(GTK_MENU_ITEM(widget), submenu);
00341 gtk_widget_show_all(submenu);
00342
00343
00344 GtkWidget *back_item = create_item(_("Back"), pixlist_icon_state("back", "normal"));
00345 g_signal_connect(G_OBJECT(back_item), "activate", G_CALLBACK(on_item_back_activate), submenu);
00346 gtk_menu_item_set_keep_active(GTK_MENU_ITEM(back_item), TRUE);
00347 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), back_item);
00348
00349 return submenu;
00350 }
00351
00352
00353 static void add_popup_separator(gpointer user_data)
00354 {
00355 GtkWidget* menu = (GtkWidget*)user_data;
00356 GtkWidget *widget = gtk_separator_menu_item_new();
00357 gtk_menu_shell_append(GTK_MENU_SHELL(menu), widget);
00358 gtk_widget_show(widget);
00359 }
00360
00361
00362 static void create_menu()
00363 {
00364 if (g_menu && !menustore_popup_has_changed()) {
00365
00366 return;
00367 }
00368 menustore_clear_popup_changed();
00369
00370 if (g_menu)
00371 {
00372
00373 gtk_widget_destroy(g_menu);
00374 g_menu = NULL;
00375 }
00376
00377
00378 GtkWidget *widget = gtk_menu_new();
00379 gtk_signal_connect(GTK_OBJECT(widget), "key-press-event", GTK_SIGNAL_FUNC(on_menu_key_press), NULL);
00380 g_signal_connect(G_OBJECT(widget), "deactivate", G_CALLBACK(on_menu_deactivate), NULL);
00381 g_signal_connect(G_OBJECT(widget), "move-scroll", G_CALLBACK(on_menu_move_scroll), NULL);
00382 g_signal_connect(G_OBJECT(widget), "move-selected", G_CALLBACK(on_menu_move_selected), NULL);
00383 g_menu = widget;
00384
00385 menustore_fill_menu(add_popup_item, add_popup_submenu, add_popup_separator, g_menu);
00386
00387 gtk_widget_show(g_menu);
00388
00389 }
00390
00391
00392 static gboolean update_display(gpointer data)
00393 {
00394 #if (TIMING_ON)
00395 stop_timer(__func__);
00396 #endif
00397 display_update_return_control( (gint) data);
00398 return FALSE;
00399 }
00400
00401
00402 static void idle_update_display(gint type)
00403 {
00404 g_idle_add(update_display, (gpointer) type);
00405 }
00406
00407
00408 static void set_active(gboolean do_active)
00409 {
00410 if (do_active == is_active) return;
00411
00412 if (do_active)
00413 {
00414 #if (TIMING_ON)
00415 start_timer();
00416 #endif
00417 display_gain_control();
00418 create_menu();
00419 gtk_menu_popup(GTK_MENU(g_menu), NULL, NULL, menu_set_position, NULL, 0, 0);
00420 idle_update_display(DM_HINT_PARTIAL);
00421 }
00422 else
00423 {
00424 gtk_menu_popdown(GTK_MENU(g_menu));
00425 }
00426
00427 is_active = do_active;
00428 }
00429