1
1
// MainWindow.cc --- Main info Window
3
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Rob Caelers & Raymond Penners
3
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Rob Caelers & Raymond Penners
4
4
// All rights reserved.
6
6
// This program is free software: you can redistribute it and/or modify
35
35
#include <unistd.h>
40
#include "AppletControl.hh"
38
#include "MainWindow.hh"
43
#include "CoreFactory.hh"
44
#include "IConfigurator.hh"
42
46
#include "TimerBoxGtkView.hh"
43
47
#include "TimerBoxControl.hh"
44
#include "MainWindow.hh"
45
#include "PreferencesDialog.hh"
46
#include "StatisticsDialog.hh"
47
#include "WindowHints.hh"
53
#include "CoreFactory.hh"
54
#include "IConfigurator.hh"
55
#include "IStatistics.hh"
57
#ifdef HAVE_DISTRIBUTION
58
#include "NetworkJoinDialog.hh"
59
#include "NetworkLogDialog.hh"
62
50
#include "Menus.hh"
64
#include <gtkmm/menu.h>
65
#include <gtkmm/stock.h>
67
#include "gtk/gtkmenu.h"
69
const string MainWindow::CFG_KEY_MAIN_WINDOW = "gui/main_window";
70
const string MainWindow::CFG_KEY_MAIN_WINDOW_ALWAYS_ON_TOP = "gui/main_window/always_on_top";
71
const string MainWindow::CFG_KEY_MAIN_WINDOW_START_IN_TRAY = "gui/main_window/start_in_tray";
72
const string MainWindow::CFG_KEY_MAIN_WINDOW_X = "gui/main_window/x";
73
const string MainWindow::CFG_KEY_MAIN_WINDOW_Y = "gui/main_window/y";
74
const string MainWindow::CFG_KEY_MAIN_WINDOW_HEAD = "gui/main_window/head";
76
52
#ifdef PLATFORM_OS_WIN32
77
53
const char *WIN32_MAIN_CLASS_NAME = "Workrave";
78
54
const UINT MYWM_TRAY_MESSAGE = WM_USER +0x100;
87
64
MainWindow::MainWindow() :
89
67
timer_box_control(NULL),
90
68
timer_box_view(NULL),
91
monitor_suspended(false),
94
69
window_location(-1, -1),
95
70
window_head_location(-1, -1),
96
71
window_relocated_location(-1, -1)
109
83
MainWindow::~MainWindow()
111
85
TRACE_ENTER("MainWindow::~MainWindow");
87
if (visible_connection.connected())
89
visible_connection.disconnect();
92
#ifdef PLATFORM_OS_WIN32
93
if (timeout_connection.connected())
95
timeout_connection.disconnect();
112
99
delete timer_box_control;
113
100
#ifdef PLATFORM_OS_WIN32
111
MainWindow::is_visible() const
113
#if defined(PLATFORM_OS_WIN32)
114
const GtkWidget *window = Gtk::Widget::gobj();
115
GdkWindow *gdk_window = window->window;
116
HWND hwnd = (HWND) GDK_WINDOW_HWND(gdk_window);
117
return IsWindowVisible(hwnd);
118
#elif defined(HAVE_GTK3)
119
return get_visible();
121
return Gtk::Window::is_visible();
127
MainWindow::toggle_window()
129
TRACE_ENTER("MainWindow::toggle_window");
131
bool visible = is_visible();
144
//! Opens the main window.
146
MainWindow::open_window()
148
TRACE_ENTER("MainWindow::open_window");
149
if (timer_box_view->get_visible_count() > 0)
151
#ifdef PLATFORM_OS_WIN32
160
set_position(Gtk::WIN_POS_NONE);
161
set_gravity(Gdk::GRAVITY_STATIC);
162
get_start_position(x, y, head);
165
GtkRequisition min_size;
166
GtkRequisition natural_size;
167
get_preferred_size(min_size, natural_size);
169
GtkRequisition min_size;
170
on_size_request(&min_size);
173
GUI::get_instance()->bound_head(x, y, min_size.width, min_size.height, head);
175
GUI::get_instance()->map_from_head(x, y, head);
176
TRACE_MSG("moving to " << x << " " << y);
179
bool always_on_top = GUIConfig::get_always_on_top();
180
WindowHints::set_always_on_top(this, always_on_top);
181
TimerBoxControl::set_enabled("main_window", true);
188
//! Closes the main window.
190
MainWindow::close_window()
192
TRACE_ENTER("MainWindow::close_window");
193
#ifdef PLATFORM_OS_WIN32
195
#elif defined(PLATFORM_OS_OSX)
208
TimerBoxControl::set_enabled("main_window", false);
214
MainWindow::set_can_close(bool can_close)
216
TRACE_ENTER_MSG("MainWindow::set_can_close", can_close);
217
this->can_close = can_close;
229
TRACE_MSG("iconify");
238
//! Updates the main window.
242
timer_box_control->update();
123
246
//! Initializes the main window.
125
248
MainWindow::init()
132
255
list<Glib::RefPtr<Gdk::Pixbuf> > icons;
134
const char *icon_files[] = { "workrave-icon-small.png",
135
"workrave-icon-medium.png",
136
"workrave-icon-large.png" };
257
const char *icon_files[] = {
258
"scalable/apps/workrave.svg",
259
"16x16/apps/workrave.png",
260
"24x24/apps/workrave.png",
261
"32x32/apps/workrave.png",
262
"48x48/apps/workrave.png",
263
"64x64/apps/workrave.png",
264
"96x96/apps/workrave.png",
265
"128x128/apps/workrave.png",
138
268
for (unsigned int i = 0; i < sizeof(icon_files) / sizeof(char *); i++)
246
379
IConfigurator *config = CoreFactory::get_configurator();
247
380
config->add_listener(TimerBoxControl::CFG_KEY_TIMERBOX + "main_window", this);
382
visible_connection = property_visible().signal_changed().connect(sigc::mem_fun(*this, &MainWindow::on_visibility_changed));
256
387
//! Setup configuration settings.
258
389
MainWindow::setup()
260
391
TRACE_ENTER("MainWindow::setup");
262
393
bool new_enabled = TimerBoxControl::is_enabled("main_window");
263
bool always_on_top = get_always_on_top();
394
bool always_on_top = GUIConfig::get_always_on_top();
396
TRACE_MSG("can_close " << new_enabled);
265
397
TRACE_MSG("enabled " << new_enabled);
266
398
TRACE_MSG("on top " << always_on_top);
413
bool visible = is_visible();
283
417
WindowHints::set_always_on_top(this, always_on_top);
286
if (is_visible() && always_on_top)
420
if (visible && always_on_top)
295
//! Updates the main window.
299
timer_box_control->update();
304
MainWindow::on_activate()
306
TRACE_ENTER("MainWindow::on_activate");
308
#ifdef PLATFORM_OS_WIN32
309
GtkWidget *window = Gtk::Widget::gobj();
310
GdkWindow *gdk_window = window->window;
311
HWND hwnd = (HWND) GDK_WINDOW_HWND(gdk_window);
313
bool visible = IsWindowVisible(hwnd);
315
bool visible = GTK_WIDGET_VISIBLE(GTK_WIDGET(gobj()));
331
//! Opens the main window.
333
MainWindow::open_window()
335
TRACE_ENTER("MainWindow::open_window");
336
if (timer_box_view->get_visible_count() > 0)
338
#ifdef PLATFORM_OS_WIN32
347
set_position(Gtk::WIN_POS_NONE);
348
set_gravity(Gdk::GRAVITY_STATIC);
349
get_start_position(x, y, head);
352
on_size_request(&req);
353
GUI::get_instance()->bound_head(x, y, req.width, req.height, head);
355
GUI::get_instance()->map_from_head(x, y, head);
356
TRACE_MSG("moving to " << x << " " << y);
359
bool always_on_top = get_always_on_top();
360
WindowHints::set_always_on_top(this, always_on_top);
362
TimerBoxControl::set_enabled("main_window", true);
369
//! Closes the main window.
371
MainWindow::close_window()
373
TRACE_ENTER("MainWindow::close_window");
374
#ifdef PLATFORM_OS_WIN32
376
#elif defined(PLATFORM_OS_OSX)
379
GUI *gui = GUI::get_instance();
381
if (applet_active || gui->is_status_icon_visible())
390
GUIConfig::set_trayicon_enabled(true);
397
431
MainWindow::on_delete_event(GdkEventAny *)
399
433
TRACE_ENTER("MainWindow::on_delete_event");
400
GUI *gui = GUI::get_instance();
434
IGUI *gui = GUI::get_instance();
401
435
assert(gui != NULL);
403
#ifdef PLATFORM_OS_WIN32
437
#if defined(PLATFORM_OS_WIN32)
404
438
win32_show(false);
405
gui->main_window_closed();
439
closed_signal.emit();
440
TimerBoxControl::set_enabled("main_window", false);
441
#elif defined(PLATFORM_OS_OSX)
443
TimerBoxControl::set_enabled("main_window", false);
407
#if defined(HAVE_GNOME) || defined(HAVE_KDE)
408
bool terminate = true;
409
AppletControl *applet_control = gui->get_applet_control();
410
if (applet_control != NULL)
412
terminate = ( !applet_control->is_visible() &&
413
!gui->is_status_icon_visible() );
448
TimerBoxControl::set_enabled("main_window", false);
418
452
gui->terminate();
423
TimerBoxControl::set_enabled("main_window", false);
425
#elif defined(PLATFORM_OS_OSX)
427
TimerBoxControl::set_enabled("main_window", false);
430
#endif // HAVE_GNOME || HAVE_KDE
431
#endif // PLATFORM_OS_WIN32
439
460
//! Users pressed some mouse button in the main window.
441
462
MainWindow::on_button_press_event(GdkEventButton *event)
444
465
bool ret = false;
448
469
#ifndef PLATFORM_OS_OSX
449
470
// No popup menu on OS X
451
472
if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3))
453
Menus::get_instance()->popup(Menus::MENU_MAINWINDOW,
454
event->button, event->time);
474
IGUI *gui = GUI::get_instance();
475
Menus *menus = gui->get_menus();
476
menus->popup(Menus::MENU_MAINWINDOW, event->button, event->time);
464
486
MainWindow::config_changed_notify(const string &key)
466
488
TRACE_ENTER_MSG("MainWindow::config_changed_notify", key);
467
if (key != CFG_KEY_MAIN_WINDOW_HEAD
468
&& key != CFG_KEY_MAIN_WINDOW_X
469
&& key != CFG_KEY_MAIN_WINDOW_Y)
489
if (key != GUIConfig::CFG_KEY_MAIN_WINDOW_HEAD
490
&& key != GUIConfig::CFG_KEY_MAIN_WINDOW_X
491
&& key != GUIConfig::CFG_KEY_MAIN_WINDOW_Y)
478
MainWindow::get_always_on_top()
481
CoreFactory::get_configurator()
482
->get_value_with_default(MainWindow::CFG_KEY_MAIN_WINDOW_ALWAYS_ON_TOP,
490
MainWindow::set_always_on_top(bool b)
492
CoreFactory::get_configurator()
493
->set_value(MainWindow::CFG_KEY_MAIN_WINDOW_ALWAYS_ON_TOP, b);
498
MainWindow::get_start_in_tray()
501
CoreFactory::get_configurator()
502
->get_value_with_default(CFG_KEY_MAIN_WINDOW_START_IN_TRAY, rc, false);
508
MainWindow::set_start_in_tray(bool b)
510
CoreFactory::get_configurator()
511
->set_value(CFG_KEY_MAIN_WINDOW_START_IN_TRAY, b);
515
499
#ifdef PLATFORM_OS_WIN32
517
501
MainWindow::win32_show(bool b)
519
TRACE_ENTER("MainWindow::win32_show");
503
TRACE_ENTER_MSG("MainWindow::win32_show", b);
520
504
bool retry = false;
522
506
// Gtk's hide() seems to quit the program.
550
535
if (show_retry_count > 0)
552
Glib::signal_timeout().connect(sigc::mem_fun(*this, &MainWindow::win32_show_retry), 50);
537
timeout_connection = Glib::signal_timeout().connect(sigc::mem_fun(*this, &MainWindow::win32_show_retry), 50);
637
622
TRACE_ENTER("MainWindow::get_start_position");
638
623
// FIXME: Default to right-bottom instead of 256x256
639
624
IConfigurator *cfg = CoreFactory::get_configurator();
640
cfg->get_value_with_default(CFG_KEY_MAIN_WINDOW_X, x, 256);
641
cfg->get_value_with_default(CFG_KEY_MAIN_WINDOW_Y, y, 256);
642
cfg->get_value_with_default(CFG_KEY_MAIN_WINDOW_HEAD, head, 0);
625
cfg->get_value_with_default(GUIConfig::CFG_KEY_MAIN_WINDOW_X, x, 256);
626
cfg->get_value_with_default(GUIConfig::CFG_KEY_MAIN_WINDOW_Y, y, 256);
627
cfg->get_value_with_default(GUIConfig::CFG_KEY_MAIN_WINDOW_HEAD, head, 0);
655
640
TRACE_ENTER_MSG("MainWindow::set_start_position",
656
641
x << " " << y << " " << head);
657
642
IConfigurator *cfg = CoreFactory::get_configurator();
658
cfg->set_value(CFG_KEY_MAIN_WINDOW_X, x);
659
cfg->set_value(CFG_KEY_MAIN_WINDOW_Y, y);
660
cfg->set_value(CFG_KEY_MAIN_WINDOW_HEAD, head);
643
cfg->set_value(GUIConfig::CFG_KEY_MAIN_WINDOW_X, x);
644
cfg->set_value(GUIConfig::CFG_KEY_MAIN_WINDOW_Y, y);
645
cfg->set_value(GUIConfig::CFG_KEY_MAIN_WINDOW_HEAD, head);
672
657
get_start_position(x, y, head);
675
on_size_request(&req);
660
GtkRequisition min_size;
661
GtkRequisition natural_size;
662
get_preferred_size(min_size, natural_size);
664
GtkRequisition min_size;
665
on_size_request(&min_size);
677
GUI::get_instance()->bound_head(x, y, req.width, req.height, head);
668
GUI::get_instance()->bound_head(x, y, min_size.width, min_size.height, head);
679
670
window_head_location.set_x(x);
680
671
window_head_location.set_y(y);
682
673
GUI::get_instance()->map_from_head(x, y, head);
684
TRACE_MSG("Main window size " << req.width << " " << req.height);
675
TRACE_MSG("Main window size " << min_size.width << " " << min_size.height);
686
677
window_location.set_x(x);
687
678
window_location.set_y(y);
697
MainWindow::set_applet_active(bool a)
699
TRACE_ENTER_MSG("MainWindow::set_applet_active", a);
704
GUI *gui = GUI::get_instance();
705
if (applet_active || gui->is_status_icon_visible())
721
MainWindow::status_icon_changed()
723
TRACE_ENTER("MainWindow::status_icon_changed");
726
GUI *gui = GUI::get_instance();
727
if (applet_active || gui->is_status_icon_visible())
741
687
MainWindow::on_configure_event(GdkEventConfigure *event)
781
727
get_position(x, y);
784
on_size_request(&req);
730
GtkRequisition min_size;
731
GtkRequisition natural_size;
732
get_preferred_size(min_size, natural_size);
734
GtkRequisition min_size;
735
on_size_request(&min_size);
738
width = min_size.width;
739
height = min_size.height;
790
742
TRACE_MSG("main window = " << x << " " << y);
792
744
if (x <= 0 && y <= 0)
847
799
x = window_head_location.get_x();
848
800
y = window_head_location.get_y();
850
GUI *gui = GUI::get_instance();
802
IGUI *gui = GUI::get_instance();
851
803
int num_heads = gui->get_number_of_heads();
852
804
for (int i = 0; i < num_heads; i++)
854
806
HeadInfo &head = gui->get_head(i);
858
on_size_request(&req);
859
GUI::get_instance()->bound_head(x, y, req.width, req.height, i);
810
GtkRequisition min_size;
811
GtkRequisition natural_size;
812
get_preferred_size(min_size, natural_size);
814
GtkRequisition min_size;
815
on_size_request(&min_size);
818
GUI::get_instance()->bound_head(x, y, min_size.width, min_size.height, i);
861
820
gui->map_from_head(x, y, i);
894
853
return DefWindowProc(hwnd, uMsg, wParam, lParam);
859
MainWindow::on_visibility_changed()
861
TRACE_ENTER("MainWindow::on_visibility_changed");
862
TRACE_MSG(is_visible());
863
visibility_changed_signal.emit();
868
MainWindow::signal_closed()
870
return closed_signal;
874
MainWindow::signal_visibility_changed()
876
return visibility_changed_signal;