VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gvviewerwindow_x.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gvviewerwindow_x.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gvviewerwindow_x.h"
23 #include "geventloop.h"
24 #include "gassert.h"
25 #include "glog.h"
26 #include <exception>
27 
28 Gv::ViewerWindowX::ViewerWindowX( ViewerWindowHandler & window_handler , ViewerWindow::Config config , int dx , int dy ) :
29  GX::Window(m_base_display,dx,dy,m_base_display.white(),config.m_title) ,
30  m_xloop(m_base_xloop) ,
31  m_window_handler(window_handler) ,
32  m_canvas(*this) ,
33  m_config(config) ,
34  m_dx(dx) ,
35  m_dy(dy) ,
36  m_mask(dx,dy,m_config.m_mask_file)
37 {
38  G_DEBUG( "Gv::ViewerWindowX::ctor: window-fd=" << windowDisplay().fd() ) ;
40 }
41 
43 {
44  GNet::EventLoop::instance().dropRead( GNet::Descriptor(windowDisplay().fd()) ) ;
45 }
46 
48 {
49  enableEvents( GX::Window::events(m_config.m_mouse_moves) ) ;
50  show() ;
51  m_xloop.runUntil( MapNotify ) ;
52 }
53 
54 void Gv::ViewerWindowX::onChar( char c )
55 {
56  m_window_handler.onChar( c ) ;
57 }
58 
59 void Gv::ViewerWindowX::onLeftMouseButtonDown( int x , int y , bool shift , bool control )
60 {
61  m_window_handler.onMouseButtonDown( x , y , shift , control ) ;
62 }
63 
64 void Gv::ViewerWindowX::onLeftMouseButtonUp( int x , int y , bool shift , bool control )
65 {
66  m_window_handler.onMouseButtonUp( x , y , shift , control ) ;
67 }
68 
69 void Gv::ViewerWindowX::onMouseMove( int x , int y )
70 {
71  m_window_handler.onMouseMove( x , y ) ;
72 }
73 
74 void Gv::ViewerWindowX::display( int data_dx , int data_dy , int data_channels , const char * data_p , size_t data_n )
75 {
76  const unsigned char * p = reinterpret_cast<const unsigned char*>(data_p) ;
77  if( m_mask.empty() && data_channels == 3 )
78  update( m_canvas.dx() , m_canvas.dy() , data_dx , data_dy , p , data_n ) ;
79  else
80  update( m_canvas.dx() , m_canvas.dy() , data_dx , data_dy , data_channels , p , data_n ) ;
81  m_canvas.blit() ;
82 
83  // take this opportunity to poll the x event queue -- this
84  // improves reliability if the process is stressed
85  int n = XPending(m_base_display.x()) ;
86  if( n )
87  m_xloop.handlePendingEvents() ;
88 }
89 
90 void Gv::ViewerWindowX::update( int x_max , int y_max , int data_dx , int data_dy ,
91  const unsigned char * p , size_t data_n )
92 {
93  // optimised overload for rgb image and no mask
94 
95  if( !m_canvas.fastable() )
96  {
97  update( x_max , y_max , data_dx , data_dy , 3 , p , data_n ) ;
98  return ;
99  }
100 
101  G_ASSERT( data_n == static_cast<size_t>(data_dx*data_dy*3) ) ;
102  int y_out = y_max - 1 ;
103  for( int y = 0 ; y < data_dy && y < y_max ; y++ , y_out-- )
104  {
105  for( int x = 0 ; x < data_dx ; x++ )
106  {
107  const unsigned int r = *p++ ;
108  const unsigned int g = *p++ ;
109  const unsigned int b = *p++ ;
110  if( x < x_max )
111  {
112  m_canvas.fastpoint( x , y_out , Gr::Colour(r,g,b) ) ;
113  }
114  }
115  }
116 }
117 
118 void Gv::ViewerWindowX::update( int x_max , int y_max , int data_dx , int data_dy , int data_channels ,
119  const unsigned char * p , size_t data_n )
120 {
121  size_t mask_offset = 0U ;
122  int y_out = y_max - 1 ;
123  for( int y = 0 ; y < data_dy && y < y_max ; y++ , y_out-- )
124  {
125  for( int x = 0 ; x < data_dx ; x++ )
126  {
127  const unsigned int r = *p++ ;
128  const unsigned int g = data_channels > 1 ? *p++ : r ;
129  const unsigned int b = data_channels > 2 ? *p++ : r ;
130  if( x < x_max )
131  {
132  if( m_mask.masked( mask_offset++ ) )
133  m_canvas.point( x , y_out , Gr::Colour(r>>1,g>>3,b>>3) ) ;
134  else
135  m_canvas.point( x , y_out , Gr::Colour(r,g,b) ) ;
136  }
137  }
138  }
139 }
140 
141 void Gv::ViewerWindowX::onExpose( XExposeEvent & event )
142 {
143  G_DEBUG( "Gv::ViewerWindowX::onExpose: exposed" ) ;
144  if( event.count == 0 )
145  m_canvas.blit() ;
146 }
147 
148 void Gv::ViewerWindowX::readEvent()
149 {
150  int n = XEventsQueued( m_base_display.x() , QueuedAlready ) ;
151  G_DEBUG( "Gv::ViewerWindowX::readEvent: event on xwindow fd: " << n ) ;
152  if( n > 3 )
153  G_WARNING( "Gv::ViewerWindowX::readEvent: backlog: " << n ) ;
154 
155  m_xloop.handlePendingEvents() ;
156 }
157 
158 void Gv::ViewerWindowX::onException( std::exception & e )
159 {
160  G_WARNING( "Gv::ViewerWindowX::onException: " << e.what() ) ;
161  throw ;
162 }
163 
165 {
166  return m_dx ;
167 }
168 
170 {
171  return m_dy ;
172 }
173 
174 /// \file gvviewerwindow_x.cpp
ViewerWindowX(ViewerWindowHandler &, ViewerWindowConfig, int dx, int dy)
Constructor.
A simple rgb colour structure.
Definition: grcolour.h:36
virtual void dropRead(Descriptor fd)=0
Removes the given event source descriptor from the list of read sources.
A class that encapsulates a network file descriptor and hides knowledge of its o/s-spefific error val...
Definition: gdescriptor.h:37
GX::Display & windowDisplay()
Returns a reference to the display as passed in to the ctor.
Definition: gxwindow.cpp:122
virtual void addRead(Descriptor fd, EventHandler &handler)=0
Adds the given event source descriptor and associated handler to the read list.
A configuration structure for Gv::ViewerWindow.
virtual int dy() const override
Override from ViewerWindow.
virtual void init() override
Override from ViewerWindow.
static long events(bool with_mouse_moves)
Returns a default event mask for enableEvents().
Definition: gxwindow.cpp:164
virtual ~ViewerWindowX()
Destructor.
virtual void display(int, int, int, const char *, size_t) override
Override from ViewerWindow.
static EventLoop & instance()
Returns a reference to an instance of the class, if any.
Definition: geventloop.cpp:43
A callback interface for Gv::ViewerWindow.
virtual int dx() const override
Override from ViewerWindow.