More dtp work. I think we're good enough to start putting all the pieces together...

This commit is contained in:
Pietro Gagliardi 2016-05-03 16:10:35 -04:00
parent afac890502
commit 218a50a2b1
1 changed files with 105 additions and 24 deletions

View File

@ -5,48 +5,125 @@
GtkWidget *win;
GtkWidget *dtp;
GdkDevice *keyboard;
GdkDevice *mouse;
// based on gtk_combo_box_list_position() in the GTK+ source code
// TODO monitor detection
static void allocationToScreen(GtkWidget *w, GtkAllocation *a)
// again, a lot of this is in the order that GtkComboBox does it
static void hidePopup(void)
{
gint x, y;
GdkWindow *window;
if (keyboard != NULL)
gdk_device_ungrab(keyboard, GDK_CURRENT_TIME);
gdk_device_ungrab(mouse, GDK_CURRENT_TIME);
gtk_device_grab_remove(win, mouse);
keyboard = NULL;
mouse = NULL;
x = 0;
y = 0;
if (!gtk_widget_get_has_window(w)) {
x = a->x;
y = a->y;
}
window = gtk_widget_get_window(w);
gdk_window_get_root_coords(window, x, y, &x, &y);
if (gtk_widget_get_direction(w) == GTK_TEXT_DIR_RTL)
x += a->width;
a->x = x;
a->y = y;
gtk_widget_hide(win);
}
static void toggled(GtkToggleButton *t, gpointer data)
static gboolean stopPopup(GtkWidget *widget, GdkEvent *event, gpointer data)
{
hidePopup();
return TRUE; // this is what GtkComboBox does
}
// this consolidates a good chunk of what GtkComboBox does
static gboolean startGrab(void)
{
GdkDevice *dev;
guint32 time;
GdkWindow *window;
dev = gtk_get_current_event_device();
if (dev == NULL)
return FALSE; // TODO
time = gtk_get_current_event_time();
keyboard = dev;
mouse = gdk_device_get_associated_device(dev);
if (gdk_device_get_source(dev) != GDK_SOURCE_KEYBOARD) {
dev = mouse;
mouse = keyboard;
keyboard = dev;
}
window = gtk_widget_get_window(win);
if (keyboard != NULL)
if (gdk_device_grab(keyboard, window,
GDK_OWNERSHIP_WINDOW, TRUE,
GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
NULL, time) != GDK_GRAB_SUCCESS)
return FALSE;
if (mouse != NULL)
if (gdk_device_grab(mouse, window,
GDK_OWNERSHIP_WINDOW, TRUE,
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
NULL, time) != GDK_GRAB_SUCCESS) {
if (keyboard != NULL)
gdk_device_ungrab(keyboard, time);
return FALSE;
}
gtk_device_grab_add(win, mouse, TRUE);
// TODO store keyboard and mouse
g_signal_connect(win, "grab-broken-event", G_CALLBACK(stopPopup), NULL);
g_signal_connect(win, "button-release-event", G_CALLBACK(stopPopup), NULL);
return TRUE;
}
// based on gtk_combo_box_list_position() in the GTK+ source code
static void allocationToScreen(GtkWidget *w, GtkAllocation *a, gint *x, gint *y)
{
GdkWindow *window;
*x = 0;
*y = 0;
if (!gtk_widget_get_has_window(w)) {
*x = a->x;
*y = a->y;
}
window = gtk_widget_get_window(w);
gdk_window_get_root_coords(window, *x, *y, x, y);
if (gtk_widget_get_direction(w) == GTK_TEXT_DIR_RTL)
*x += a->width; // TODO subtract target width
// TODO monitor detection
*y += a->height;
}
static void showPopup(GtkWidget *button)
{
GtkWidget *toplevel;
GtkAllocation allocation;
gint x, y;
toplevel = gtk_widget_get_toplevel(GTK_WIDGET(t));
toplevel = gtk_widget_get_toplevel(button);
if (GTK_IS_WINDOW(toplevel))
gtk_window_group_add_window(gtk_window_get_group(GTK_WINDOW(toplevel)),
GTK_WINDOW(win));
gtk_widget_get_allocation(GTK_WIDGET(t), &allocation);
allocationToScreen(GTK_WIDGET(t), &allocation);
gtk_window_move(GTK_WINDOW(win), allocation.x, allocation.y + allocation.height);
gtk_widget_get_allocation(button, &allocation);
allocationToScreen(button, &allocation, &x, &y);
gtk_window_move(GTK_WINDOW(win), x, y);
gtk_widget_show_all(win);
gtk_widget_show(win);
if (!startGrab())
hidePopup();
}
// TODO verify signature
static void toggled(GtkToggleButton *t, gpointer data)
{
if (gtk_toggle_button_get_active(t))
showPopup(GTK_WIDGET(t));
else
hidePopup();
}
int main(void)
{
GtkWidget *mainwin;
GtkWidget *box;
GtkWidget *button;
gtk_init(NULL, NULL);
@ -54,9 +131,12 @@ int main(void)
mainwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(mainwin, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_container_set_border_width(GTK_CONTAINER(mainwin), 12);
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
gtk_container_add(GTK_CONTAINER(mainwin), box);
button = gtk_toggle_button_new_with_label("Click");
g_signal_connect(button, "toggled", G_CALLBACK(toggled), NULL);
gtk_container_add(GTK_CONTAINER(mainwin), button);
gtk_container_add(GTK_CONTAINER(box), button);
gtk_container_add(GTK_CONTAINER(box), gtk_entry_new());
win = gtk_window_new(GTK_WINDOW_POPUP);
gtk_window_set_resizable(GTK_WINDOW(win), FALSE);
@ -74,6 +154,7 @@ int main(void)
dtp = GTK_WIDGET(g_object_new(dateTimePickerWidget_get_type(), NULL));
gtk_container_add(GTK_CONTAINER(win), dtp);
gtk_widget_show(dtp);
gtk_widget_show_all(mainwin);
gtk_main();