5 #define YUILogComponent "gtk"
6 #include <yui/Libyui_config.h>
10 #include <YDialogSpy.h>
11 #include <YPushButton.h>
12 #include <gdk/gdkkeysyms.h>
15 #include "ygtkwindow.h"
30 #define DEFAULT_CHAR_WIDTH 60
31 #define DEFAULT_CHAR_HEIGHT 28
32 #define DEFAULT_PIXEL_WIDTH 330
33 #define DEFAULT_PIXEL_HEIGHT 200
45 GdkCursor *m_busyCursor;
49 YGWindowCloseFn m_canClose;
54 m_widget = ygtk_window_new();
56 # if GTK_CHECK_VERSION (3, 12, 0)
58 gtk_container_set_resize_mode (GTK_CONTAINER (m_widget), GTK_RESIZE_PARENT);
61 g_object_ref_sink (G_OBJECT (m_widget));
63 # if GTK_CHECK_VERSION (3, 14, 0)
65 gtk_window_set_has_resize_grip (GTK_WINDOW (m_widget), TRUE);
75 std::stack<YDialog *> &stack = YDialog::_dialogStack;
76 YDialog *ylast = stack.size() ? stack.top() : 0;
77 if (ylast == ydialog) {
78 if (stack.size() > 1) {
88 GtkWindow *parent = NULL;
91 parent = GTK_WINDOW (yglast->m_window->getWidget());
93 GtkWindow *window = GTK_WINDOW (m_widget);
95 std::string dialogTitle =
"YaSt";
97 #ifdef LIBYUI_VERSION_NUM
98 #if LIBYUI_VERSION_AT_LEAST(2,42,3)
99 dialogTitle = YUI::app()->applicationTitle();
104 gtk_window_set_title (window, dialogTitle.c_str());
105 gtk_window_set_modal (window, TRUE);
106 gtk_window_set_transient_for (window, parent);
107 gtk_window_set_type_hint (window, GDK_WINDOW_TYPE_HINT_DIALOG);
108 AtkObject *peer = gtk_widget_get_accessible (GTK_WIDGET (window));
110 atk_object_set_role (peer, ATK_ROLE_DIALOG);
113 gtk_window_set_title (window, dialogTitle.c_str());
114 #ifdef LIBYUI_VERSION_NUM
115 #if LIBYUI_VERSION_AT_LEAST(2,42,3)
116 GdkPixbuf *pixbuf = YGUtils::loadPixbuf (YUI::app()->applicationIcon());
118 gtk_window_set_default_icon (pixbuf);
119 g_object_unref (G_OBJECT (pixbuf));
123 if (YGUI::ui()->unsetBorder())
124 gtk_window_set_decorated (window, FALSE);
128 int width = YUI::app()->defaultWidth();
129 int height = YUI::app()->defaultHeight();
130 gtk_window_set_default_size ( window, width, height );
131 gtk_window_resize( window, width, height );
132 if (YGUI::ui()->setFullscreen())
133 gtk_window_fullscreen (window);
135 gtk_window_set_role (window,
"yast2");
141 g_signal_connect (G_OBJECT (m_widget),
"delete-event",
142 G_CALLBACK (close_window_cb),
this);
143 g_signal_connect_after (G_OBJECT (m_widget),
"key-press-event",
144 G_CALLBACK (key_pressed_cb),
this);
145 g_signal_connect (G_OBJECT (m_widget),
"focus-in-event",
146 G_CALLBACK (focus_in_event_cb),
this);
148 g_signal_connect_after (G_OBJECT (m_widget),
"realize",
149 G_CALLBACK (realize_cb),
this);
156 g_object_unref (G_OBJECT (m_busyCursor));
157 gtk_widget_destroy (m_widget);
158 g_object_unref (G_OBJECT (m_widget));
162 { gtk_widget_show (m_widget); }
167 gdk_window_set_cursor (gtk_widget_get_window(m_widget), NULL);
174 GdkDisplay *display = gtk_widget_get_display (m_widget);
175 m_busyCursor = gdk_cursor_new_for_display (display, GDK_WATCH);
176 g_object_ref (G_OBJECT (m_busyCursor));
179 GdkDisplay *display = gtk_widget_get_display (m_widget);
180 gdk_window_set_cursor (gtk_widget_get_window(m_widget), m_busyCursor);
181 gdk_display_sync(display);
186 void setChild (YWidget *new_child)
188 GtkWidget *child = gtk_bin_get_child (GTK_BIN (m_widget));
190 gtk_container_remove (GTK_CONTAINER (m_widget), child);
192 child = YGWidget::get (new_child)->getLayout();
193 gtk_container_add (GTK_CONTAINER (m_widget), child);
200 window->m_refcount++;
203 static void unref (
YGWindow *window)
205 if (--window->m_refcount == 0) {
206 bool is_main_window = (window == main_window);
214 GtkWidget *getWidget() {
return m_widget; }
215 YWidget *getChild() {
return m_child; }
220 if (!m_canClose || m_canClose (m_canCloseData))
221 YGUI::ui()->sendEvent (
new YCancelEvent());
224 static gboolean close_window_cb (GtkWidget *widget, GdkEvent *event,
233 static gboolean key_pressed_cb (GtkWidget *widget, GdkEventKey *event,
237 if (event->keyval == GDK_KEY_Escape &&
238 main_window != pThis) {
244 if (event->state & GDK_SHIFT_MASK) {
245 switch (event->keyval) {
247 YGUI::ui()->askSaveLogs();
253 if ((event->state & GDK_CONTROL_MASK) && (event->state & GDK_SHIFT_MASK)
254 && (event->state & GDK_MOD1_MASK)) {
255 yuiMilestone() <<
"Caught YaST2 magic key combination\n";
257 switch (event->keyval) {
259 YGUI::ui()->makeScreenShot();
262 YGUI::ui()->toggleRecordMacro();
265 YGUI::ui()->askPlayMacro();
268 YGUI::ui()->sendEvent (
new YDebugEvent());
271 yuiMilestone() <<
"Starting xterm\n";
272 ret = system (
"/usr/bin/xterm &");
274 yuiError() <<
"Can't launch xterm (error code" << ret <<
")" << std::endl;
277 yuiMilestone() <<
"Opening dialog spy" << std::endl;
278 YDialogSpy::showDialogSpy();
279 YGUI::ui()->normalCursor();
288 static gboolean focus_in_event_cb (GtkWidget *widget, GdkEventFocus *event)
289 { gtk_window_set_urgency_hint (GTK_WINDOW (widget), FALSE);
return FALSE; }
291 static void realize_cb (GtkWidget *widget,
YGWindow *pThis)
292 { pThis->busyCursor(); }
295 YGDialog::YGDialog (YDialogType dialogType, YDialogColorMode colorMode)
296 : YDialog (dialogType, colorMode),
297 YGWidget (this, NULL, YGTK_HBOX_NEW(0), NULL)
300 m_stickyTitle =
false;
301 m_containee = gtk_event_box_new();
302 if (dialogType == YMainDialog && main_window)
303 m_window = main_window;
305 m_window =
new YGWindow (dialogType == YMainDialog,
this);
306 YGWindow::ref (m_window);
308 if (colorMode != YDialogNormalColor) {
310 GtkWidget *icon = gtk_image_new_from_icon_name
311 (colorMode == YDialogWarnColor ?
"dialog-warning" :
"dialog-information",
312 GTK_ICON_SIZE_DIALOG);
314 # if GTK_CHECK_VERSION (3, 14, 0)
315 gtk_widget_set_halign (icon, GTK_ALIGN_CENTER);
316 gtk_widget_set_valign (icon, GTK_ALIGN_START);
317 gtk_widget_set_margin_start (icon, 0);
318 gtk_widget_set_margin_end (icon, 0);
319 gtk_widget_set_margin_top (icon, 12);
320 gtk_widget_set_margin_bottom (icon, 12);
322 gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0);
323 gtk_misc_set_padding (GTK_MISC (icon), 0, 12);
326 gtk_box_pack_start (GTK_BOX (getWidget()), icon, FALSE, FALSE, 12);
327 gtk_box_pack_start (GTK_BOX (getWidget()), m_containee, TRUE, TRUE, 0);
330 gtk_box_pack_start (GTK_BOX (getWidget()), m_containee, TRUE, TRUE, 0);
331 gtk_widget_show_all (getWidget());
337 m_window->setChild (
this);
340 YGDialog::~YGDialog()
342 YGWindow::unref (m_window);
347 YDialog::setDefaultButton( 0 );
348 if ( newDefaultButton )
350 newDefaultButton->setKeyboardFocus();
351 YDialog::setDefaultButton(newDefaultButton);
355 void YGDialog::openInternal()
360 void YGDialog::activate()
362 m_window->setChild (
this);
365 void YGDialog::present()
367 GtkWindow *window = GTK_WINDOW (m_window->getWidget());
368 if (!gtk_window_is_active (window))
369 gtk_window_set_urgency_hint (window, TRUE);
374 YDialog *ydialog = YDialog::currentDialog (
false);
376 return static_cast <YGDialog *
> (ydialog);
380 GtkWindow *YGDialog::currentWindow()
382 YGDialog *ydialog = YGDialog::currentDialog();
384 return GTK_WINDOW (ydialog->m_window->getWidget());
388 void YGDialog::setCloseCallback (YGWindowCloseFn canClose,
void *canCloseData)
390 m_window->m_canClose = canClose;
391 m_window->m_canCloseData = canCloseData;
394 void YGDialog::unsetCloseCallback()
396 m_window->m_canClose = NULL;
399 void YGDialog::normalCursor()
401 m_window->normalCursor();
404 void YGDialog::busyCursor()
406 m_window->busyCursor();
411 void YGDialog::doSetSize (
int width,
int height)
417 GtkWidget *window = m_window->getWidget();
420 gtk_window_get_size(GTK_WINDOW (window), &w, &h);
422 if (w < width || h < height) {
424 width = MAX (width, w),
425 height = MAX (height, h);
428 if (gtk_widget_get_realized (window)) {
429 gtk_widget_queue_resize (window);
430 width = MIN (width, YUI::app()->displayWidth());
431 height = MIN (height, YUI::app()->displayHeight());
432 if (isMainDialog()) {
433 GtkAllocation allocation;
434 gtk_widget_get_allocation(window, &allocation);
435 if (allocation.width < width || allocation.height < height) {
437 width = MAX (width, allocation.width),
438 height = MAX (height, allocation.height);
444 int lpass = layoutPass();
448 gtk_window_resize (GTK_WINDOW (window), width, height);
450 gtk_window_set_default_size (GTK_WINDOW (window), width, height);
454 void YGDialog::highlight (YWidget *ywidget)
457 static gboolean draw_highlight_cb (GtkWidget *widget, cairo_t *cr)
459 int w = gtk_widget_get_allocated_width(widget);
460 int h = gtk_widget_get_allocated_height(widget);
462 cairo_rectangle (cr, 0, 0, w, h);
463 cairo_set_source_rgb (cr, 0xff/255.0, 0x88/255.0, 0);
468 static bool hasWindow (GtkWidget *widget)
470 if (gtk_widget_get_has_window(widget))
473 for (GList *children = gdk_window_peek_children (gtk_widget_get_window(widget));
474 children; children = children->next) {
475 GdkWindow *child = (GdkWindow *) children->data;
477 gdk_window_get_user_data (child, &data);
478 if ((GtkWidget *) data == widget)
485 static YWidget *previousWidget = NULL;
486 if (previousWidget && previousWidget->isValid()) {
487 YGWidget *prev = YGWidget::get (previousWidget);
489 GtkWidget *widget = prev->getWidget();
490 if (inner::hasWindow (widget)) {
491 gtk_widget_override_background_color (widget, GTK_STATE_FLAG_NORMAL, NULL);
492 gtk_widget_override_color (widget, GTK_STATE_FLAG_NORMAL, NULL);
495 g_signal_handlers_disconnect_by_func (widget,
496 (gpointer) inner::draw_highlight_cb, NULL);
497 gtk_widget_queue_draw (widget);
502 YGWidget *ygwidget = YGWidget::get (ywidget);
504 GtkWidget *widget = ygwidget->getWidget();
505 if (inner::hasWindow (widget)) {
506 GdkRGBA bg_color = { 0, 0xffff, 0xaaaa, 0 };
507 GdkRGBA base_color = { 0, 0xffff, 0xeeee, 0 };
508 gtk_widget_override_background_color (widget, GTK_STATE_FLAG_NORMAL, &bg_color);
509 gtk_widget_override_color (widget, GTK_STATE_FLAG_NORMAL, &base_color);
512 g_signal_connect (G_OBJECT (widget),
"draw",
513 G_CALLBACK (inner::draw_highlight_cb), NULL);
514 gtk_widget_queue_draw (widget);
518 previousWidget = ywidget;
521 void YGDialog::setTitle (
const std::string &title,
bool sticky)
525 if (!m_stickyTitle || sticky) {
526 GtkWindow *window = GTK_WINDOW (m_window->getWidget());
527 gchar *str = g_strdup_printf (
"%s - YaST", title.c_str());
528 gtk_window_set_title (window, str);
530 m_stickyTitle = sticky;
536 void ygdialog_setTitle (
const gchar *title, gboolean sticky);
539 void ygdialog_setTitle (
const gchar *title, gboolean sticky)
541 YGDialog::currentDialog()->setTitle (title, sticky);
544 void YGDialog::setIcon (
const std::string &icon)
546 GtkWindow *window = GTK_WINDOW (m_window->getWidget());
547 GdkPixbuf *pixbuf = YGUtils::loadPixbuf (icon);
549 gtk_window_set_icon (window, pixbuf);
550 g_object_unref (G_OBJECT (pixbuf));
554 typedef bool (*FindWidgetsCb) (YWidget *widget,
void *data) ;
556 static void findWidgets (
557 std::list <YWidget *> *widgets, YWidget *widget, FindWidgetsCb find_cb,
void *cb_data)
559 if (find_cb (widget, cb_data))
560 widgets->push_back (widget);
561 for (YWidgetListConstIterator it = widget->childrenBegin();
562 it != widget->childrenEnd(); it++)
563 findWidgets (widgets, *it, find_cb, cb_data);
566 static bool IsFunctionWidget (YWidget *widget,
void *data)
567 {
return widget->functionKey() == GPOINTER_TO_INT (data); }
569 YWidget *YGDialog::getFunctionWidget (
int key)
571 std::list <YWidget *> widgets;
572 findWidgets (&widgets,
this, IsFunctionWidget, GINT_TO_POINTER (key));
573 return widgets.empty() ? NULL : widgets.front();
576 static bool IsClassWidget (YWidget *widget,
void *data)
577 {
return !strcmp (widget->widgetClass(), (
char *) data); }
579 std::list <YWidget *> YGDialog::getClassWidgets (
const char *className)
581 std::list <YWidget *> widgets;
582 findWidgets (&widgets,
this, IsClassWidget, (
void *) className);
586 YDialog *YGWidgetFactory::createDialog (YDialogType dialogType, YDialogColorMode colorMode)
587 {
return new YGDialog (dialogType, colorMode); }
589 YEvent *YGDialog::waitForEventInternal (
int timeout_millisec)
590 {
return YGUI::ui()->waitInput (timeout_millisec,
true); }
592 YEvent *YGDialog::pollEventInternal()
593 {
return YGUI::ui()->waitInput (0,
false); }
void setDefaultButton(YPushButton *newDefaultButton)
Set the dialog's default button.