X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fprompt.c;h=785b46c747cc15999f0ac1de40414f1a7d21ff23;hb=d09fd3183e6a52c63fcfdcf62d418cfdccb0015b;hp=d4dcbb7bf856bdd46a3fa90085de98fcefaa8f6e;hpb=c70379fa8f771e499a4d47e84af06d71838b780d;p=chaz%2Fopenbox diff --git a/openbox/prompt.c b/openbox/prompt.c index d4dcbb7b..785b46c7 100644 --- a/openbox/prompt.c +++ b/openbox/prompt.c @@ -28,7 +28,6 @@ #include "gettext.h" static GList *prompt_list = NULL; -static GList *prompt_msg_list = NULL; /* we construct these */ static RrAppearance *prompt_a_bg; @@ -51,18 +50,19 @@ static void prompt_layout(ObPrompt *self); static void render_all(ObPrompt *self); static void render_button(ObPrompt *self, ObPromptElement *e); static void prompt_resize(ObPrompt *self, gint w, gint h); +static void prompt_run_callback(ObPrompt *self, gint result); void prompt_startup(gboolean reconfig) { RrColor *c_button, *c_focus, *c_press, *c_pfocus; /* note: this is not a copy, don't free it */ - prompt_a_bg = ob_rr_theme->osd_hilite_bg; + prompt_a_bg = ob_rr_theme->osd_bg; - prompt_a_button = RrAppearanceCopy(ob_rr_theme->a_focused_unpressed_close); - prompt_a_focus = RrAppearanceCopy(ob_rr_theme->a_hover_focused_close); - prompt_a_press = RrAppearanceCopy(ob_rr_theme->a_focused_pressed_close); - prompt_a_pfocus = RrAppearanceCopy(ob_rr_theme->a_focused_pressed_close); + prompt_a_button = RrAppearanceCopy(ob_rr_theme->btn_close->a_focused_unpressed); + prompt_a_focus = RrAppearanceCopy(ob_rr_theme->btn_close->a_hover_focused); + prompt_a_press = RrAppearanceCopy(ob_rr_theme->btn_close->a_focused_pressed); + prompt_a_pfocus = RrAppearanceCopy(ob_rr_theme->btn_close->a_focused_pressed); c_button = prompt_a_button->texture[0].data.mask.color; c_focus = prompt_a_focus->texture[0].data.mask.color; @@ -95,7 +95,7 @@ void prompt_startup(gboolean reconfig) prompt_a_button->texture[0].data.text.color = c_button; prompt_a_focus->texture[0].data.text.color = c_focus; prompt_a_press->texture[0].data.text.color = c_press; - prompt_a_pfocus->texture[0].data.text.color = c_press; + prompt_a_pfocus->texture[0].data.text.color = c_pfocus; prompt_a_focus->texture[1].data.lineart.color = c_focus; prompt_a_focus->texture[2].data.lineart.color = c_focus; @@ -122,8 +122,16 @@ void prompt_startup(gboolean reconfig) void prompt_shutdown(gboolean reconfig) { - while (prompt_msg_list) - prompt_cancel(prompt_msg_list->data); + GList *it; + + if (!reconfig) { + for (it = prompt_list; it; it = g_list_next(it)) { + ObPrompt *p = it->data; + if (p->cleanup) p->cleanup(p, p->data); + } + + g_assert(prompt_list == NULL); + } RrAppearanceFree(prompt_a_button); RrAppearanceFree(prompt_a_focus); @@ -132,10 +140,11 @@ void prompt_shutdown(gboolean reconfig) RrAppearanceFree(prompt_a_msg); } -ObPrompt* prompt_new(const gchar *msg, +ObPrompt* prompt_new(const gchar *msg, const gchar *title, const ObPromptAnswer *answers, gint n_answers, gint default_result, gint cancel_result, - ObPromptCallback func, gpointer data) + ObPromptCallback func, ObPromptCleanup cleanup, + gpointer data) { ObPrompt *self; XSetWindowAttributes attrib; @@ -143,9 +152,10 @@ ObPrompt* prompt_new(const gchar *msg, attrib.override_redirect = FALSE; - self = g_new0(ObPrompt, 1); + self = g_slice_new0(ObPrompt); self->ref = 1; self->func = func; + self->cleanup = cleanup; self->data = data; self->default_result = default_result; self->cancel_result = cancel_result; @@ -156,11 +166,17 @@ ObPrompt* prompt_new(const gchar *msg, CopyFromParent, CWOverrideRedirect, &attrib); + self->ic = obt_keyboard_context_new(self->super.window, + self->super.window); /* make it a dialog type window */ OBT_PROP_SET32(self->super.window, NET_WM_WINDOW_TYPE, ATOM, OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DIALOG)); + /* set the window's title */ + if (title) + OBT_PROP_SETS(self->super.window, NET_WM_NAME, title); + /* listen for key presses on the window */ self->event_mask = KeyPressMask; @@ -225,6 +241,8 @@ void prompt_unref(ObPrompt *self) prompt_list = g_list_remove(prompt_list, self); + obt_keyboard_context_unref(self->ic); + for (i = 0; i < self->n_buttons; ++i) { window_remove(self->button[i].window); XDestroyWindow(obt_display, self->button[i].window); @@ -232,7 +250,7 @@ void prompt_unref(ObPrompt *self) XDestroyWindow(obt_display, self->msg.window); XDestroyWindow(obt_display, self->super.window); - g_free(self); + g_slice_free(ObPrompt, self); } } @@ -251,9 +269,8 @@ static void prompt_layout(ObPrompt *self) b += OUTSIDE_MARGIN; { - Rect *area = screen_physical_area_all_monitors(); + const Rect *area = screen_physical_area_all_monitors(); maxw = MIN(MAX_WIDTH, area->width*4/5); - g_free(area); } /* find the button sizes and how much space we need for them */ @@ -278,7 +295,6 @@ static void prompt_layout(ObPrompt *self) self->button[i].width = MAX(self->button[i].width, bw); self->button[i].height = MAX(self->button[i].height, bh); - self->button[i].width += BUTTON_HMARGIN * 2; self->button[i].height += BUTTON_VMARGIN * 2; @@ -398,10 +414,10 @@ static void render_button(ObPrompt *self, ObPromptElement *e) { RrAppearance *a; - if (e->pressed && self->focus == e) a = prompt_a_pfocus; - else if (self->focus == e) a = prompt_a_focus; - else if (e->pressed) a = prompt_a_press; - else a = prompt_a_button; + if (e->hover && self->focus == e) a = prompt_a_pfocus; + else if (self->focus == e) a = prompt_a_focus; + else if (e->pressed) a = prompt_a_press; + else a = prompt_a_button; a->surface.parent = prompt_a_bg; a->surface.parentx = e->x; @@ -446,7 +462,7 @@ void prompt_show(ObPrompt *self, ObClient *parent, gboolean modal) /* activate the prompt */ OBT_PROP_MSG(ob_screen, self->super.window, NET_ACTIVE_WINDOW, 1, /* from an application.. */ - event_curtime, + event_time(), 0, 0, 0); return; @@ -507,35 +523,31 @@ void prompt_hide(ObPrompt *self) gboolean prompt_key_event(ObPrompt *self, XEvent *e) { gboolean shift; - guint shift_mask; + guint shift_mask, mods; + KeySym sym; if (e->type != KeyPress) return FALSE; shift_mask = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT); - shift = !!(e->xkey.state & shift_mask); + mods = obt_keyboard_only_modmasks(e->xkey.state); + shift = !!(mods & shift_mask); /* only accept shift */ - if (e->xkey.state != 0 && e->xkey.state != shift_mask) + if (mods != 0 && mods != shift_mask) return FALSE; - if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) + sym = obt_keyboard_keypress_to_keysym(e); + + if (sym == XK_Escape) prompt_cancel(self); - else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN) || - e->xkey.keycode == ob_keycode(OB_KEY_SPACE)) - { - if (self->func) self->func(self, self->focus->result, self->data); - prompt_hide(self); - } - else if (e->xkey.keycode == ob_keycode(OB_KEY_TAB) || - e->xkey.keycode == ob_keycode(OB_KEY_LEFT) || - e->xkey.keycode == ob_keycode(OB_KEY_RIGHT)) - { + else if (sym == XK_Return || sym == XK_KP_Enter || sym == XK_space) + prompt_run_callback(self, self->focus->result); + else if (sym == XK_Tab || sym == XK_Left || sym == XK_Right) { gint i; gboolean left; ObPromptElement *oldfocus; - left = e->xkey.keycode == ob_keycode(OB_KEY_LEFT) || - (e->xkey.keycode == ob_keycode(OB_KEY_TAB) && shift); + left = (sym == XK_Left) || ((sym == XK_Tab) && shift); oldfocus = self->focus; for (i = 0; i < self->n_buttons; ++i) @@ -575,27 +587,28 @@ gboolean prompt_mouse_event(ObPrompt *self, XEvent *e) oldfocus = self->focus; - but->pressed = TRUE; + but->pressed = but->hover = TRUE; self->focus = but; if (oldfocus != but) render_button(self, oldfocus); render_button(self, but); } else if (e->type == ButtonRelease) { - if (but->pressed) { - if (self->func) self->func(self, but->result, self->data); - prompt_hide(self); - } + if (but->hover) + prompt_run_callback(self, but->result); + but->pressed = FALSE; } else if (e->type == MotionNotify) { - gboolean press; + if (but->pressed) { + gboolean hover; - press = (e->xmotion.x >= 0 && e->xmotion.y >= 0 && - e->xmotion.x < but->width && e->xmotion.y < but->height); + hover = (e->xmotion.x >= 0 && e->xmotion.y >= 0 && + e->xmotion.x < but->width && e->xmotion.y < but->height); - if (press != but->pressed) { - but->pressed = press; - render_button(self, but); + if (hover != but->hover) { + but->hover = hover; + render_button(self, but); + } } } return TRUE; @@ -603,24 +616,41 @@ gboolean prompt_mouse_event(ObPrompt *self, XEvent *e) void prompt_cancel(ObPrompt *self) { - if (self->func) self->func(self, self->cancel_result, self->data); - prompt_hide(self); + prompt_run_callback(self, self->cancel_result); } -static void prompt_show_message_cb(ObPrompt *p, int res, gpointer data) +static gboolean prompt_show_message_cb(ObPrompt *p, int res, gpointer data) +{ + return TRUE; /* call the cleanup func */ +} + +static void prompt_show_message_cleanup(ObPrompt *p, gpointer data) { - prompt_msg_list = g_list_remove(prompt_msg_list, p); prompt_unref(p); } -void prompt_show_message(const gchar *msg, const gchar *answer) +ObPrompt* prompt_show_message(const gchar *msg, const gchar *title, + const gchar *answer) { ObPrompt *p; ObPromptAnswer ans[] = { { answer, 0 } }; - p = prompt_new(msg, ans, 1, 0, 0, prompt_show_message_cb, NULL); - prompt_msg_list = g_list_prepend(prompt_msg_list, p); + p = prompt_new(msg, title, ans, 1, 0, 0, + prompt_show_message_cb, prompt_show_message_cleanup, NULL); prompt_show(p, NULL, FALSE); + return p; +} + +static void prompt_run_callback(ObPrompt *self, gint result) +{ + prompt_ref(self); + if (self->func) { + gboolean clean = self->func(self, self->focus->result, self->data); + if (clean && self->cleanup) + self->cleanup(self, self->data); + } + prompt_hide(self); + prompt_unref(self); }