Skip to content

Commit fd1c236

Browse files
committed
Support for print dialogs (#221).
Downgraded to GTK 2.0 to support various dialogs easily.
1 parent 170d7c3 commit fd1c236

15 files changed

+1077
-5
lines changed

.vscode/settings.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"files.exclude": {
3+
"**/*.o": true,
4+
"**/*.o.deps": true,
5+
"**/build": true
6+
},
7+
"workbench.colorTheme": "Default Light+",
8+
"window.zoomLevel": 0,
9+
"C_Cpp.default.includePath": [
10+
"/usr/include/gtk-2.0/",
11+
"/usr/include/gtk-unix-print-2.0/",
12+
"/usr/include/glib-2.0/",
13+
"/usr/include/pango-1.0/",
14+
"/usr/include/cairo/",
15+
"/usr/include/gdk-pixbuf-2.0/",
16+
"/usr/include/atk-1.0/",
17+
"/usr/lib/x86_64-linux-gnu/gtk-2.0/include/",
18+
"/usr/lib/x86_64-linux-gnu/glib-2.0/include/",
19+
"/usr/lib/x86_64-linux-gnu/gtk-unix-print-2.0/",
20+
"/usr/lib/x86_64-linux-gnu/pango-1.0/",
21+
"/usr/lib/x86_64-linux-gnu/cairo/",
22+
"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/",
23+
"/usr/lib/x86_64-linux-gnu/atk-1.0/",
24+
"/home/cz/github/phpdesktop-linux70/src/",
25+
],
26+
"html.format.wrapLineLength": 80,
27+
"editor.wordWrap": "wordWrapColumn",
28+
"editor.rulers": [80],
29+
}

Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,26 @@ TARGET=build/bin/phpdesktop
33
INCLUDES = -Isrc -Lbuild/lib -Lbuild/bin
44

55
CCFLAGS = -g -Wall -Werror -std=gnu++11 -pthread $(INCLUDES)
6-
CCFLAGS += $(shell pkg-config --cflags glib-2.0 gtk+-3.0)
6+
CCFLAGS += $(shell pkg-config --cflags glib-2.0 gtk+-2.0 gtk+-unix-print-2.0)
77

88
CFLAGS_OPTIMIZE = -O3 -fvisibility=hidden
99

1010
LDFLAGS = -Wl,-rpath,. -Wl,-rpath,"\$$ORIGIN" -lX11 -lcef -lcef_dll_wrapper -Wl,--as-needed -ldl -lpthread
11-
LDFLAGS += $(shell pkg-config --libs glib-2.0 gtk+-3.0)
11+
LDFLAGS += $(shell pkg-config --libs glib-2.0 gtk+-2.0 gtk+-unix-print-2.0)
1212

1313
OBJS=\
1414
src/main.o \
1515
src/app.o \
1616
src/client_handler.o \
1717
src/gtk.o \
1818
src/json.o \
19+
src/main_message_loop.o \
20+
src/main_message_loop_std.o \
1921
src/mongoose.o \
2022
src/mongoose_server.o \
23+
src/print_handler_gtk.o \
2124
src/settings.o \
25+
src/util_gtk.o \
2226
src/utils.o \
2327

2428
CC=g++

src/app.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,16 @@
44

55
#include "app.h"
66
#include "include/wrapper/cef_helpers.h"
7+
#include "print_handler_gtk.h"
78

89
App::App() {
910
}
1011

1112
void App::OnContextInitialized() {
1213
CEF_REQUIRE_UI_THREAD();
14+
print_handler_ = new ClientPrintHandlerGtk();
15+
}
16+
17+
CefRefPtr<CefPrintHandler> App::GetPrintHandler() {
18+
return print_handler_;
1319
}

src/app.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ class App : public CefApp,
1919

2020
// CefBrowserProcessHandler methods:
2121
virtual void OnContextInitialized() override;
22+
virtual CefRefPtr<CefPrintHandler> GetPrintHandler() override;
2223

2324
private:
25+
CefRefPtr<CefPrintHandler> print_handler_;
26+
2427
// Include the default reference counting implementation.
2528
IMPLEMENT_REFCOUNTING(App);
2629
};

src/gtk.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@
88
#include "include/cef_app.h"
99
#include "include/base/cef_logging.h"
1010

11+
namespace {
12+
GtkWidget* g_main_window = NULL;
13+
} // namespace
14+
1115
GtkWidget* create_gtk_window(const char* title, const char* icon,
1216
bool center, int width, int height) {
1317
// Create window.
1418
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
19+
g_main_window = window;
1520

1621
// Signals
1722
g_signal_connect(G_OBJECT(window), "size-allocate",
@@ -52,6 +57,10 @@ GtkWidget* create_gtk_window(const char* title, const char* icon,
5257
return vbox;
5358
}
5459

60+
GtkWidget* get_main_window() {
61+
return g_main_window;
62+
}
63+
5564
::Window get_window_xid(GtkWidget* window) {
5665
GdkWindow* gdk_window = gtk_widget_get_window(window);
5766
if (!gdk_window) {
@@ -109,6 +118,7 @@ void window_focus_out_signal(GtkWidget* widget, gpointer data) {
109118
}
110119

111120
void window_destroy_signal(GtkWidget* widget, gpointer data) {
121+
g_main_window = NULL;
112122
CefQuitMessageLoop();
113123
}
114124

src/gtk.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include <stdlib.h>
66
#include <string.h>
77
#include <gtk/gtk.h>
8-
#include <gtk/gtkx.h>
98
#include <gdk/gdk.h>
109
#include <gdk/gdkx.h>
1110
#include <gdk-pixbuf/gdk-pixdata.h>
@@ -15,6 +14,7 @@
1514
GtkWidget* create_gtk_window(const char* title, const char* icon,
1615
bool center, int width, int height);
1716
::Window get_window_xid(GtkWidget* window);
17+
GtkWidget* get_main_window();
1818
void window_size_allocate_signal(GtkWidget* widget, GtkAllocation *alloc,
1919
gpointer data);
2020
void window_focus_in_signal(GtkWidget* widget, gpointer data);

src/main.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "utils.h"
88
#include "mongoose_server.h"
99
#include "settings.h"
10+
#include "main_message_loop_std.h"
1011

1112
#include "include/base/cef_logging.h"
1213
#include "include/wrapper/cef_helpers.h"
@@ -180,6 +181,9 @@ int main(int argc, char **argv) {
180181
// Initialize GDK threads before CEF.
181182
gdk_threads_init();
182183

184+
scoped_ptr<MainMessageLoop> message_loop;
185+
message_loop.reset(new MainMessageLoopStd);
186+
183187
// Log messages created by LOG() macro will be written to debug.log
184188
// file only after CEF was initialized. Before CEF is initialized
185189
// all logs are only printed to console.
@@ -219,15 +223,19 @@ int main(int argc, char **argv) {
219223
LOG(INFO) << "Top window xid=" << xid;
220224
create_browser(xid);
221225

222-
CefRunMessageLoop();
226+
// Run the message loop. This will block until Quit() is called.
227+
int result = message_loop->Run();
223228

224229
LOG(INFO) << "Stop Mongoose server";
225230
mongoose_stop();
226231

227232
LOG(INFO) << "Shutdown CEF";
228233
CefShutdown();
229234

230-
return 0;
235+
// Release objects in reverse order of creation.
236+
message_loop.reset();
237+
238+
return result;
231239
}
232240

233241
void create_browser(::Window xid) {

src/main_message_loop.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copied from upstream CEF with minor modifications for PHP Desktop
2+
// purposes.
3+
4+
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
5+
// reserved. Use of this source code is governed by a BSD-style license that
6+
// can be found in the LICENSE file.
7+
8+
#include "main_message_loop.h"
9+
10+
#include "include/cef_task.h"
11+
#include "include/wrapper/cef_closure_task.h"
12+
13+
namespace {
14+
15+
MainMessageLoop* g_main_message_loop = NULL;
16+
17+
} // namespace
18+
19+
MainMessageLoop::MainMessageLoop() {
20+
DCHECK(!g_main_message_loop);
21+
g_main_message_loop = this;
22+
}
23+
24+
MainMessageLoop::~MainMessageLoop() {
25+
g_main_message_loop = NULL;
26+
}
27+
28+
// static
29+
MainMessageLoop* MainMessageLoop::Get() {
30+
DCHECK(g_main_message_loop);
31+
return g_main_message_loop;
32+
}
33+
34+
void MainMessageLoop::PostClosure(const base::Closure& closure) {
35+
PostTask(CefCreateClosureTask(closure));
36+
}
37+

src/main_message_loop.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copied from upstream CEF with minor modifications for PHP Desktop
2+
// purposes.
3+
4+
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
5+
// reserved. Use of this source code is governed by a BSD-style license that
6+
// can be found in the LICENSE file.
7+
8+
#ifndef CEF_TESTS_SHARED_BROWSER_MAIN_MESSAGE_LOOP_H_
9+
#define CEF_TESTS_SHARED_BROWSER_MAIN_MESSAGE_LOOP_H_
10+
#pragma once
11+
12+
#include "include/base/cef_bind.h"
13+
#include "include/base/cef_scoped_ptr.h"
14+
#include "include/cef_task.h"
15+
16+
#if defined(OS_WIN)
17+
#include <windows.h>
18+
#endif
19+
20+
// Represents the message loop running on the main application thread in the
21+
// browser process. This will be the same as the CEF UI thread on Linux, OS X
22+
// and Windows when not using multi-threaded message loop mode. The methods of
23+
// this class are thread-safe unless otherwise indicated.
24+
class MainMessageLoop {
25+
public:
26+
// Returns the singleton instance of this object.
27+
static MainMessageLoop* Get();
28+
29+
// Run the message loop. The thread that this method is called on will be
30+
// considered the main thread. This blocks until Quit() is called.
31+
virtual int Run() = 0;
32+
33+
// Quit the message loop.
34+
virtual void Quit() = 0;
35+
36+
// Post a task for execution on the main message loop.
37+
virtual void PostTask(CefRefPtr<CefTask> task) = 0;
38+
39+
// Returns true if this message loop runs tasks on the current thread.
40+
virtual bool RunsTasksOnCurrentThread() const = 0;
41+
42+
#if defined(OS_WIN)
43+
// Set the current modeless dialog on Windows for proper delivery of dialog
44+
// messages when using multi-threaded message loop mode. This method must be
45+
// called from the main thread. See http://support.microsoft.com/kb/71450 for
46+
// background.
47+
virtual void SetCurrentModelessDialog(HWND hWndDialog) = 0;
48+
#endif
49+
50+
// Post a closure for execution on the main message loop.
51+
void PostClosure(const base::Closure& closure);
52+
53+
protected:
54+
// Only allow deletion via scoped_ptr.
55+
friend struct base::DefaultDeleter<MainMessageLoop>;
56+
57+
MainMessageLoop();
58+
virtual ~MainMessageLoop();
59+
60+
private:
61+
DISALLOW_COPY_AND_ASSIGN(MainMessageLoop);
62+
};
63+
64+
#define CURRENTLY_ON_MAIN_THREAD() \
65+
MainMessageLoop::Get()->RunsTasksOnCurrentThread()
66+
67+
#define REQUIRE_MAIN_THREAD() DCHECK(CURRENTLY_ON_MAIN_THREAD())
68+
69+
#define MAIN_POST_TASK(task) MainMessageLoop::Get()->PostTask(task)
70+
71+
#define MAIN_POST_CLOSURE(closure) \
72+
MainMessageLoop::Get()->PostClosure(closure)
73+
74+
// Use this struct in conjuction with RefCountedThreadSafe to ensure that an
75+
// object is deleted on the main thread. For example:
76+
//
77+
// class Foo : public base::RefCountedThreadSafe<Foo, DeleteOnMainThread> {
78+
// public:
79+
// Foo();
80+
// void DoSomething();
81+
//
82+
// private:
83+
// // Allow deletion via scoped_refptr only.
84+
// friend struct DeleteOnMainThread;
85+
// friend class base::RefCountedThreadSafe<Foo, DeleteOnMainThread>;
86+
//
87+
// virtual ~Foo() {}
88+
// };
89+
//
90+
// base::scoped_refptr<Foo> foo = new Foo();
91+
// foo->DoSomething();
92+
// foo = NULL; // Deletion of |foo| will occur on the main thread.
93+
//
94+
struct DeleteOnMainThread {
95+
template <typename T>
96+
static void Destruct(const T* x) {
97+
if (CURRENTLY_ON_MAIN_THREAD()) {
98+
delete x;
99+
} else {
100+
MainMessageLoop::Get()->PostClosure(
101+
base::Bind(&DeleteOnMainThread::Destruct<T>, x));
102+
}
103+
}
104+
};
105+
106+
#endif // CEF_TESTS_SHARED_BROWSER_MAIN_MESSAGE_LOOP_H_

src/main_message_loop_std.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copied from upstream CEF with minor modifications for PHP Desktop
2+
// purposes.
3+
4+
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
5+
// reserved. Use of this source code is governed by a BSD-style license that
6+
// can be found in the LICENSE file.
7+
8+
#include "main_message_loop_std.h"
9+
10+
#include "include/cef_app.h"
11+
12+
MainMessageLoopStd::MainMessageLoopStd() {}
13+
14+
int MainMessageLoopStd::Run() {
15+
CefRunMessageLoop();
16+
return 0;
17+
}
18+
19+
void MainMessageLoopStd::Quit() {
20+
CefQuitMessageLoop();
21+
}
22+
23+
void MainMessageLoopStd::PostTask(CefRefPtr<CefTask> task) {
24+
CefPostTask(TID_UI, task);
25+
}
26+
27+
bool MainMessageLoopStd::RunsTasksOnCurrentThread() const {
28+
return CefCurrentlyOn(TID_UI);
29+
}
30+
31+
#if defined(OS_WIN)
32+
void MainMessageLoopStd::SetCurrentModelessDialog(HWND hWndDialog) {
33+
// Nothing to do here. The Chromium message loop implementation will
34+
// internally route dialog messages.
35+
}
36+
#endif

0 commit comments

Comments
 (0)